如何根据特定条件按 SQL 分组?
How to group by SQL based on certain conditions?
我使用的是 Microsoft SQL Server 2014,我有以下关于看电视的人的数据:
这里的时间是从午夜算起的分钟数。
PersonId StartTime EndTime
1 300 600
1 250 700
1 200 800
1 900 1200
2 100 200
现在如你所见,我想得到的是第1个人的观看陈述分组如下:
250 - 700 与 300 - 600 重叠,所以我想做的是从开始时间开始取最小值,从结束时间取最大值,因为它们重叠,我想对第 1 个人的所有观看陈述都这样做.但是我怎样才能用一个分组来做到这一点呢?
谢谢
缺口和孤岛
DECLARE @TVWatchingTime TABLE (PersonId int, StartTime int, EndTime int)
INSERT INTO @TVWatchingTime
VALUES
(1, 300, 600),
(1, 250, 700),
(1, 200, 800),
(1, 900, 1200),
(2, 100, 200)
;WITH cteSource(PersonId, StartTime, EndTime)
AS
(
SELECT
s.PersonId, s.StartTime, e.EndTime
FROM
(
SELECT PersonId, StartTime, ROW_NUMBER() OVER (ORDER BY StartTime) AS rn
FROM @TVWatchingTime
) AS s
INNER JOIN
(
SELECT PersonId, EndTime, ROW_NUMBER() OVER (ORDER BY EndTime) + 1 AS rn
FROM @TVWatchingTime
) AS e ON s.PersonId = e.PersonId AND e.rn = s.rn
WHERE s.StartTime > e.EndTime
UNION ALL
SELECT PersonId, MIN(StartTime), MAX(EndTime)
FROM @TVWatchingTime
GROUP BY PersonId
), cteGrouped(PersonId, theTime, grp)
AS (
SELECT PersonId, u.theTime,
(ROW_NUMBER() OVER (ORDER BY u.theTime) - 1) / 2
FROM cteSource AS s
UNPIVOT (
theTime
FOR theColumn IN (s.StartTime, s.EndTime)
) AS u
)
SELECT PersonId, MIN(theTime) StartTime, MAX(theTime) EndTime
FROM cteGrouped
GROUP BY PersonId, grp
ORDER BY PersonId, grp
Returns:
PersonId StartTime EndTime
1 200 800
1 900 1200
2 100 200
我使用的是 Microsoft SQL Server 2014,我有以下关于看电视的人的数据:
这里的时间是从午夜算起的分钟数。
PersonId StartTime EndTime
1 300 600
1 250 700
1 200 800
1 900 1200
2 100 200
现在如你所见,我想得到的是第1个人的观看陈述分组如下:
250 - 700 与 300 - 600 重叠,所以我想做的是从开始时间开始取最小值,从结束时间取最大值,因为它们重叠,我想对第 1 个人的所有观看陈述都这样做.但是我怎样才能用一个分组来做到这一点呢?
谢谢
缺口和孤岛
DECLARE @TVWatchingTime TABLE (PersonId int, StartTime int, EndTime int)
INSERT INTO @TVWatchingTime
VALUES
(1, 300, 600),
(1, 250, 700),
(1, 200, 800),
(1, 900, 1200),
(2, 100, 200)
;WITH cteSource(PersonId, StartTime, EndTime)
AS
(
SELECT
s.PersonId, s.StartTime, e.EndTime
FROM
(
SELECT PersonId, StartTime, ROW_NUMBER() OVER (ORDER BY StartTime) AS rn
FROM @TVWatchingTime
) AS s
INNER JOIN
(
SELECT PersonId, EndTime, ROW_NUMBER() OVER (ORDER BY EndTime) + 1 AS rn
FROM @TVWatchingTime
) AS e ON s.PersonId = e.PersonId AND e.rn = s.rn
WHERE s.StartTime > e.EndTime
UNION ALL
SELECT PersonId, MIN(StartTime), MAX(EndTime)
FROM @TVWatchingTime
GROUP BY PersonId
), cteGrouped(PersonId, theTime, grp)
AS (
SELECT PersonId, u.theTime,
(ROW_NUMBER() OVER (ORDER BY u.theTime) - 1) / 2
FROM cteSource AS s
UNPIVOT (
theTime
FOR theColumn IN (s.StartTime, s.EndTime)
) AS u
)
SELECT PersonId, MIN(theTime) StartTime, MAX(theTime) EndTime
FROM cteGrouped
GROUP BY PersonId, grp
ORDER BY PersonId, grp
Returns:
PersonId StartTime EndTime
1 200 800
1 900 1200
2 100 200