关于SQL递归查询问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于SQL递归查询问题相关的知识,希望对你有一定的参考价值。

MSSQL数据库有两个表如下图,怎样用with as递归查询出所有不属于中国的城市?即B表中每一个向上递归查询父阶编号RegionPID,最终的RegionPID不等于01的,结果应该如表C。非常感谢各位大侠!
又如,010102的深圳,RegionPID为0101,而0101的RegionPID为01,所以不符合。
另:不能上传附件,测试脚本放在百度云盘
http://pan.baidu.com/s/1sjkkv5V
A

B

C

参考技术A 我来测一下,等会上传结果

你还有一个表没用到。
WITH cte AS (
SELECT RegionID,RegionName,RegionPID FROM [tbRegionTree] WHERE regionPID='01'
UNION ALL
SELECT d.RegionID,d.RegionName,d.RegionPID FROM cte c inner JOIN [tbRegionTree] d ON d.regionPID=c.RegionID

)
SELECT * FROM cte
上面是找到 01 中国的。

下面为非中国的。 条件上处理下
WITH cte AS (
SELECT RegionID,RegionName,RegionPID FROM [tbRegionTree] WHERE regionPID NOT LIKE '01%'
UNION ALL
SELECT d.RegionID,d.RegionName,d.RegionPID FROM cte c inner JOIN [tbRegionTree] d ON d.regionPID=c.RegionID

)
SELECT * FROM cte追问

你好,有点点问题。
RegionID是完全没规律的,所以没办法用WHERE regionPID NOT LIKE '01%'排除,我这里只是举个简单例子,实际表数据不是这样的。

能不能结合表B,把B中的每个城市都向上查询到根级,看根级regionPID是不是01?非常感谢大侠的回答。。。

追答

你的B表没用。1,和A表数据一样,2,没有主从列。
regionPID 这是你是需要确定的唯一值,你要找出对应的规律。
我用not like 本身也只是示例下,排除掉 01

你如果要通过B表的中国来判断,那二表一关联即可。最简单的二表关系就可以解决

本回答被提问者和网友采纳
参考技术B select * from dbo.tbRegionInfo where RegionID NOT LIKE '01%' AND Len(RegionID)>2

我发现根本就没必要用到你的tbRegionTree表 

看起来你的表没有设计好。。。

参考技术C 递归干嘛,你RegionID就是一个绝对地址。Like就好了。追问

你好,RegionID是完全没有规律的,这里只是举个例子

追答

说明你数据保存处理不太好,会导致你出现这种需求时,需要大量的计算。当然,目前也只能写一个游标存储过程来生成每个ID的绝对地址(如:第一级节点ID/第二级节点ID。。。)。

需要关于 Sql 递归查询的帮助

【中文标题】需要关于 Sql 递归查询的帮助【英文标题】:Need Help on Sql recursive query 【发布时间】:2019-06-26 02:37:41 【问题描述】:

我需要模拟生产订单的结束日期/时间。例如:生产订单需要 4:55 小时,但可能有 1 或 2 个休息时间,可能还有 1 个午餐时间,具体取决于所需时间和当前时间。我需要计算当前时间和生产时间之间的所有关闭时间。我只是不知道递归查询是否有用。

create table [TeamBreak]
(
  Team int ,
  StartBreak datetime,
  EndBreak datetime 
);

insert into [TeamBreak] values
(1, '1900-01-01 09:00', '1900-01-01 09:15'),
(1, '1900-01-01 12:00', '1900-01-01 12:30'),
(1, '1900-01-01 14:15', '1900-01-01 14:30'),
(2, '1900-01-01 18:15', '1900-01-01 18:30'),
(2, '1900-01-01 01:15', '1900-01-01 01:30')

DECLARE @start AS datetime='2019-01-31 7:00'
DECLARE @end AS datetime='2019-01-31 11:50' --prodction end date without break

SELECT SUM(iif(@end BETWEEN t.startbreak AND t.endbreak, DATEDIFF(n,t.startbreak,@end), DATEDIFF(n,t.startbreak,t.endbreak))) AS newtime
FROM teambreak AS t
WHERE CAST(t.startbreak AS time) 
    BETWEEN CAST(@start AS time) AND CAST(@end AS time) 
    OR CAST(t.endbreak AS time) BETWEEN CAST(@start as time) AND CAST(@end AS time)

顺便说一句,break 必须是日期时间类型而不是时间,因为 Access 前端应用程序不支持时间类型。

让我们从早上 7 点开始(不休息的第一个结束日期生产是 11 点 55 分或 4 点 55 分),上午 9 点到 9 点 15 点午餐时间中午 12 点到 12 点 30 分休息。 结果应该是添加生产结束日期的 40 分钟,而不是 15 分钟。

所以它将是 7h00+4h55=11h55 + 15minutes(break)=12h10 enddate(但由于午餐时间不可能),所以真正的结束日期将是 12:40pm(因为 12h-12:30 已关闭) . 这。我的第一个结果结束日期是下午 12:10,但好的应该是下午 12:40

【问题讨论】:

您使用的是哪个 dbms? (该代码是特定于产品的。) 当您创建一个新问题并添加 SQL 标记时,会向您显示一个大建议,即您应该为您正在使用的特定 DBMS 添加一个标记,因为它们之间的功能和语法不同。请edit您的问题这样做。在您这样做之前,任何答案都是猜测,可能无法满足您的特定需求,这会浪费您和撰写答案的人的时间。如果您希望我们为您提供帮助,您需要提供必要的信息。 不清楚你的要求是什么 您的意思是要在2019-01-31 7:002019-01-31 11:50 之间找到以分钟为单位的休息时间吗? 【参考方案1】:

用了一阵子终于找到了一个简单的方法……不是复活的CTE

首先,它在 9:15-9:30 找到了休息时间。 它增加了 15 分钟到 11:55。现在结束日期是 12:10。 第二个循环它找到了午餐时间标准 它增加了 30 分钟到 12:10。现在结束日期是我想要的 12:40

declare @start as datetime='2019-01-31 07:00'    
declare @end as datetime='2019-01-31 11:55' --prudction end date without break1
declare @newEndDate as datetime    
declare @newAddTime as int=0    
declare @newAddTimeTotal as int=0
set @newEndDate=@end    
while( 1=1)    
begin    
    select @newAddTime=     
    coalesce(sum    
    (    
    case 
        when 
            CAST(@start AS TIME) between cast(t.startbreak  as time ) and     cast(t.endbreak as time) then datediff(n, CAST(@start AS TIME),cast(t.endbreak as time))
        else 
            datediff(n, CAST(t.startbreak AS TIME),cast(t.endbreak as time))
        end),0)
    ,@start=max(t.endbreak) 
    from teambreak t        
    where (cast(@start as time) <cast (t.endbreak as time)  and  cast(@end as time)>     cast(t.startbreak as time))        
    set @end =dateadd(n,@newAddTime,@end);
set  @newAddTimeTotal= @newAddTimeTotal+@newAddTime
    if @newAddTime=0
    break;
end

select @newAddTimeTotal,@end

【讨论】:

以上是关于关于SQL递归查询问题的主要内容,如果未能解决你的问题,请参考以下文章

SQL递归查询知多少

sql server 递归查询

SQL问题 实现递归查询

sql 怎么递归查询的方法:

sql 递归查询

SQL Server CTE 和递归示例