使用时间跨度对相同值的连续行进行分组

Mor*_*lus 13 sql t-sql sql-server

抱歉模糊的标题(我只是不知道如何描述这个难题)

为教室提供以下计划表:

????????????????????????????????????????????????????????????
? Classroom ? CourseName ?  Lesson   ? StartTime ? EndTime ?
????????????????????????????????????????????????????????????
?      1001 ? Course 1   ? Lesson 1  ?      0800 ?    0900 ?
?      1001 ? Course 1   ? Lesson 2  ?      0900 ?    1000 ?
?      1001 ? Course 1   ? Lesson 3  ?      1000 ?    1100 ?
?      1001 ? Course 2   ? Lesson 10 ?      1100 ?    1200 ?
?      1001 ? Course 2   ? Lesson 11 ?      1200 ?    1300 ?
?      1001 ? Course 1   ? Lesson 4  ?      1300 ?    1400 ?
?      1001 ? Course 1   ? Lesson 5  ?      1400 ?    1500 ?
????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

我想将表格分组以显示:

????????????????????????????????????????????????
? Classroom ? CourseName ? StartTime ? EndTime ?
????????????????????????????????????????????????
?      1001 ? Course 1   ?      0800 ?    1100 ?
?      1001 ? Course 2   ?      1100 ?    1300 ?
?      1001 ? Course 1   ?      1300 ?    1500 ?
????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

基本上我们正在查看一个时间表,显示哪个crouse在某个时间段内使用什么教室......

我最初的想法是:由集团ClassroomCourseName采取MaxMinstart\end时间,但不会给我的时间跨度,它会显示仿佛课程1是使用Classroom从08:00 -在中间没有中断16:00.

Fuz*_*ree 8

该查询确定各行EndTime使用NOT EXISTS,以确保不同类型的其他类或课程的课程范围内的间的定期StartTimeEndTime,然后使用MINGROUP BY查找StartTime.

NOT EXISTS部分可确保有没有"休息"之间StartTimeEndTime范围通过搜索有任何行EndTime之间StartTimeEndTime,但属于不同的CourseNameCourseRoom.

SELECT    
    t0.ClassRoom,
    t0.CourseName,
    MIN(t0.StartTime),
    t0.EndTime
FROM (
    SELECT 
    t1.ClassRoom,
    t1.CourseName,
    t1.StartTime,
    (
        SELECT MAX(t2.EndTime)
        FROM tableA t2
        WHERE t2.CourseName = t1.CourseName
        AND t2.ClassRoom = t1.ClassRoom
        AND NOT EXISTS (SELECT 1 FROM tableA t3
            WHERE t3.EndTime < t2.EndTime 
            AND t3.EndTime > t1.EndTime
            AND (t3.CourseName <> t2.CourseName 
            OR t3.ClassRoom <> t2.ClassRoom)
        )
    ) EndTime
    FROM tableA t1
) t0 GROUP BY t0.ClassRoom, t0.CourseName, t0.EndTime
Run Code Online (Sandbox Code Playgroud)

http://www.sqlfiddle.com/#!6/39d4b/9


Ser*_*ton 5

如果您使用的是SQLServer 2012或更高版本,则可以使用它LAG来获取列的先前值,然后SUM() OVER (ORDER BY ...)创建一个滚动总和,在这种情况下,该总和可以计算CourseName的变化,可以用作GROUP BY锚点

With A AS (
  SELECT ClassRoom
       , CourseName
       , StartTime
       , EndTime
       , PrevCourse = LAG(CourseName, 1, CourseName) OVER (ORDER BY StartTime)
  FROM   Table1
), B AS (
  SELECT ClassRoom
       , CourseName
       , StartTime
       , EndTime
       , Ranker = SUM(CASE WHEN CourseName = PrevCourse THEN 0 ELSE 1 END)
                OVER (ORDER BY StartTime, CourseName)
  FROM   A
)
SELECT ClassRoom
     , CourseName
     , MIN(StartTime) StartTime
     , MAX(EndTime) EndTime
FROM   B
GROUP BY ClassRoom, CourseName, Ranker
ORDER BY StartTime
Run Code Online (Sandbox Code Playgroud)

SQLFiddle demo