关于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
你还有一个表没用到。
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表的中国来判断,那二表一关联即可。最简单的二表关系就可以解决
我发现根本就没必要用到你的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:00
和2019-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递归查询问题的主要内容,如果未能解决你的问题,请参考以下文章