Sql server 2012 聚合重叠数据

Sql server 2012 聚合重叠数据,sql-server-2012,Sql Server 2012,我有一张名为dbo.StayData的桌子。此表中有4列GuestID、StayID、CheckIn、CheckOut。我试图写一个报告,将返回3列GuestID,签入,签出。但是,如果客人的住宿重叠,例如一行的签出与另一行的签入相同,或者一行的签入介于另一个条目的签入和签出之间,我希望将这些合并到一个条目中,以便更好地了解何时发生了全程旅行。下面我在左边有一个数据样本,在右边有一个期望结果样本。我对所有的想法都持开放态度。我曾想过尝试制作临时表格,但我不确定如何达到我想要的位置 我认为这个问

我有一张名为dbo.StayData的桌子。此表中有4列GuestID、StayID、CheckIn、CheckOut。我试图写一个报告,将返回3列GuestID,签入,签出。但是,如果客人的住宿重叠,例如一行的签出与另一行的签入相同,或者一行的签入介于另一个条目的签入和签出之间,我希望将这些合并到一个条目中,以便更好地了解何时发生了全程旅行。下面我在左边有一个数据样本,在右边有一个期望结果样本。我对所有的想法都持开放态度。我曾想过尝试制作临时表格,但我不确定如何达到我想要的位置

我认为这个问题应该能够回答我的问题,但我并不真正理解代码

我使用了上述问题答案中的代码,当我看到临时桌上的一位客人时,我能够让它正常工作。但是,我试图修改该代码以查看整个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;

下面是我现在使用的最后一段代码,它似乎是有效的。我将子查询向上移动到折叠位置部分的联接中,还向最终选择添加了distinct

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;

下面是我现在使用的最后一段代码,它似乎是有效的。我将子查询向上移动到折叠位置部分的联接中,还向最终选择添加了distinct

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;