我有一个名为dbo.StayData的表。在此表中,有4列GuestID,StayID,CheckIn,CheckOut。我正在尝试编写一个报告,返回3列GuestID,CheckIN,CheckOut。但是,如果客人的重叠位置如CheckOuton,则一行与另一行的CheckIn相同,或者如果一行上的CheckIn位于不同条目的CheckIn和CheckOut之间,我想将它们合并为一个条目,这样我就能更好地了解完整行程何时发生。下面我在左边有一个数据样本,在右边有一个想要的结果样本。我对所有想法持开放态度。我曾想过尝试制作临时表,但我不确定如何到达我想去的地方。
我认为这个问题应该能够回答我的问题但我并不真正理解代码。 SQL - Consolidate Overlapping Data
我在上面的问题中使用了答案中的代码,并且能够在查看临时表中的1个访客时使其正常工作。但是我试图修改那个代码来查看整个dbo.StayData表,它有100k的行和10k的GuestID。以下是修改后我想出的内容。
with temp_positions as --Select all limits as a single column along with the start / end flag (s / e)
(
select GuestID,CheckIn as limit, 's' as pos from dbo.StayData
union
select GuestID,CheckOut as limit, 'e' as pos from dbo.StayData
)
, ordered_positions as --Rank all limits
(
select GuestID,limit, pos, RANK() OVER (ORDER BY GuestID,limit) AS Rank
from temp_positions
)
, collapsed_positions as --Collapse ranges (select the first limit, if s is preceded or followed by e, and the last limit) and rank limits again
(
select op1.*, RANK() OVER (ORDER BY Op1.GuestID,op1.Rank) AS New_Rank
from ordered_positions op1
inner join ordered_positions op2
on (op1.Rank = op2.Rank and op1.Rank = 1 and op1.pos = 's')
or (op2.Rank = op1.Rank-1 and op2.pos = 'e' and op1.pos = 's')
or (op2.Rank = op1.Rank+1 and op2.pos = 's' and op1.pos = 'e')
or (op2.Rank = op1.Rank and op1.pos = 'e' and op1.Rank = (select max(Rank) from ordered_positions))
)
, final_positions as --Now each s is followed by e. So, select s limits and corresponding e limits. Rank ranges
(
select Cp1.GuestID,cp1.limit as cp1_limit, cp2.limit as cp2_limit, RANK() OVER (ORDER BY cp1.GuestID, cp1.limit) AS Final_Rank
from collapsed_positions cp1
inner join collapsed_positions cp2
on cp1.pos = 's' and cp2.New_Rank = cp1.New_Rank+1
)
--Finally, subtract 1 from Rank to start Range #'s from 0
select fp.GuestID, fp.Final_Rank-1 seq_no, fp.cp1_limit as starty, fp.cp2_limit as endy
from final_positions fp;
答案 0 :(得分:0)
以下是我现在使用的最终代码,它似乎有效。我将Subquery向上移动到折叠位置部分的连接上,我还为最终选择添加了不同。
with temp_positions as --Select all limits as a single column along with the start / end flag (s / e)
(
select GuestID,CheckIn as limit, 's' as pos from dbo.StayData
union
select GuestID,CheckOut as limit, 'e' as pos from dbo.StayData
)
, ordered_positions as --Rank all limits
(
select GuestID,limit, pos, RANK() OVER (ORDER BY GuestID,limit) AS Rank
from temp_positions
)
, collapsed_positions as --Collapse ranges (select the first limit, if s is preceded or followed by e, and the last limit) and rank limits again
(
select op1.*, RANK() OVER (ORDER BY Op1.GuestID,op1.Rank) AS New_Rank
from ordered_positions op1
Left Join (Select GuestID, Max(Rank) as Rank from Ordered_Positions Group by GuestID) as OP
on OP1.Rank = OP.Rank
inner join ordered_positions op2
on (op1.Rank = op2.Rank and op1.Rank = 1 and op1.pos = 's')
or (op2.Rank = op1.Rank-1 and op2.pos = 'e' and op1.pos = 's')
or (op2.Rank = op1.Rank+1 and op2.pos = 's' and op1.pos = 'e')
or (op2.Rank = op1.Rank and op1.pos = 'e' and op1.Rank = OP.Rank)
)
, final_positions as --Now each s is followed by e. So, select s limits and corresponding e limits. Rank ranges
(
select Cp1.GuestID,cp1.limit as cp1_limit, cp2.limit as cp2_limit, RANK() OVER (ORDER BY cp1.GuestID, cp1.limit) AS Final_Rank
from collapsed_positions cp1
inner join collapsed_positions cp2
on cp1.pos = 's' and cp2.New_Rank = cp1.New_Rank+1
)
--Finally, subtract 1 from Rank to start Range #'s from 0
select distinct fp.GuestID, fp.Final_Rank-1 seq_no, fp.cp1_limit as starty, fp.cp2_limit as endy
from final_positions fp;