我有一个表,它会随着时间的推移将ID映射到关联ID(AssocID),并且数据库的构建每年只有一条记录。我想在每个关联期间累积一张记录。
当前示例:
ID AssocID Start End
1 a 2000 2001
1 a 2001 2002
1 b 2002 2003
1 b 2003 2004
1 a 2004 2005
...
1 a 2017 2018
2 c 2000 2001
2 c 2001 2002
2 d 2002 2003
...
2 d 2017 2018
我试图让它看起来更像这样:
ID AssocID Start End
1 a 2000 2002
1 b 2002 2004
1 a 2004 2018
2 c 2000 2002
2 d 2002 2018
我的主要问题是ID'1'会在一段时间后回到AssocID'a'并使用DISTINCT(ID,AssocID)和MIN(Start)错过第二次ID'1'映射到AssocID'a'
任何帮助表示赞赏:)
答案 0 :(得分:1)
你可以使用它。
-- Sample Data
DECLARE @MyTable TABLE (ID INT, AssocID VARCHAR(10), Start INT, [End] INT)
INSERT INTO @MyTable VALUES
(1, 'a', 2000, 2001),
(1, 'a', 2001, 2002),
(1, 'b', 2002, 2003),
(1, 'b', 2003, 2004),
(1, 'a', 2004, 2005),
(1, 'a', 2017, 2018),
(2, 'c', 2000, 2001),
(2, 'c', 2001, 2002),
(2, 'd', 2002, 2003),
(2, 'd', 2017, 2018)
-- Query
SELECT ID, AssocID, MIN(Start) [Start], MAX([End]) [End] FROM
( SELECT *,
GRP = ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Start) - ROW_NUMBER() OVER(PARTITION BY ID, AssocID ORDER BY Start)
FROM @MyTable ) T
GROUP BY ID, AssocID, GRP
ORDER BY ID, [Start]
结果:
ID AssocID Start End
----------- ---------- ----------- -----------
1 a 2000 2002
1 b 2002 2004
1 a 2004 2018
2 c 2000 2002
2 d 2002 2018
答案 1 :(得分:1)
这是间隙和岛屿问题的一个例子。您需要首先确定每个小组的开始grp_start
,然后group by
每个grp
以找到min
/ max
declare @T table (ID int, AssocID varchar(3), Start int, [End] int)
insert into @T (ID, AssocID, Start, [End]) values
(1, 'a', 2000, 2001),(1, 'a', 2001, 2002),(1, 'b', 2002, 2003),(1, 'b', 2003, 2004),(1, 'a', 2004, 2005),(1, 'a', 2005, 2006),(1, 'a', 2006, 2007),(1, 'a', 2007, 2008),(1, 'a', 2008, 2009),(1, 'a', 2009, 2010),(1, 'a', 2010, 2011),(1, 'a', 2011, 2012),(1, 'a', 2012, 2013),(1, 'a', 2013, 2014),(1, 'a', 2014, 2015),(1, 'a', 2015, 2016),(1, 'a', 2016, 2017),(1, 'a', 2017, 2018),(2, 'c', 2000, 2001),(2, 'c', 2001, 2002),(2, 'd', 2002, 2003),(2, 'd', 2017, 2018)
select
ID,
AssocID,
min(Start),
max([End])
from
(
select *,
sum([grp_start]) over (partition by ID, AssocID order by [End]) as grp
from
(
select *,
case
when
lag([End]) over (partition by ID, AssocID order by [End]) <> [Start]
then 1 else 0
end as [grp_start]
from @T
) as T
)as T
group by ID, AssocID, grp
order by ID, min(Start), max([End])