如何比较同一张表的2条记录?

时间:2014-11-23 07:52:50

标签: sql sql-server tsql

我有一个表中的时间表相关数据如下。

ScheduledID    StartTime  EndTime   ModifiedTimeStamp

1              10 AM      6 PM      01-01-2014 09:00
1              11 AM      6 PM      01-01-2014 09:30
1              11 AM      7 PM      01-01-2014 10:00
1              10 AM      6 PM      01-01-2014 10:30
1              11 AM      8 PM      01-01-2014 11:00

如上所述,计划开始和结束时间会多次修改。

我需要显示以下数据。

ScheduledID    StartTime  EndTime   ModifiedTimeStamp   Action Type

1              10 AM      6 PM      01-01-2014 09:00    Schedule Created
1              11 AM      6 PM      01-01-2014 09:30    Start Time Modified from 10AM to 11AM
1              11 AM      7 PM      01-01-2014 10:00    End Time Modified from 6PM to 7PM
1              10 AM      6 PM      01-01-2014 10:30    Start Time Modified from 11AM to 10AM, End Time Modified from 7PM to 6PM
1              11 AM      8 PM      01-01-2014 11:00    Current Schedule

请指导我如何实现这一目标?

谢谢。

2 个答案:

答案 0 :(得分:4)

如果您使用的是SQL Server 2012或更高版本,则可以使用LAG()LEAD()窗口函数来访问上一行和下一行,并使用如下所示的查询来呈现您想要的结果:

-- 2012+ version 
SELECT 
    ScheduledID, StartTime, EndTime, ModifiedTimeStamp,
    CASE 
       WHEN prevts IS NULL THEN 'Schedule created' 
       WHEN prevStartTime <> StartTime AND prevEndTime = EndTime AND nextts IS NOT NULL 
          THEN CONCAT('Start Time Modified FROM ', prevStartTime, ' to ', StartTime)
       WHEN prevStartTime <> StartTime AND prevEndTime <> EndTime AND nextts IS NOT NULL 
          THEN CONCAT('Start Time Modified FROM ', prevStartTime, ' to ', StartTime, 
          ', End Time Modified FROM ', prevEndTime, ' to ', EndTime)
       WHEN prevStartTime = StartTime AND prevEndTime <> EndTime AND nextts IS NOT NULL 
          THEN CONCAT('End Time Modified FROM ', prevEndTime, ' to ', EndTime)
       WHEN nextts IS NULL 
          THEN 'Current Schedule' 
    END as 'Action Type'
FROM (
SELECT 
    ScheduledID, 
    prevStartTime = LAG(StartTime)  OVER (PARTITION by ScheduledID ORDER BY ModifiedTimeStamp), 
    StartTime, 
    nextStartTime = LEAD(StartTime) OVER (PARTITION by ScheduledID ORDER BY ModifiedTimeStamp), 
    prevEndTime   = LAG(EndTime)     OVER (PARTITION by ScheduledID ORDER BY ModifiedTimeStamp), 
    EndTime, 
    nextEndTime = LEAD(EndTime)  OVER (PARTITION by ScheduledID ORDER BY ModifiedTimeStamp), 
    prevts = LAG(ModifiedTimeStamp) OVER (PARTITION by ScheduledID ORDER BY ModifiedTimeStamp), 
    ModifiedTimeStamp, 
    nextts = LEAD(ModifiedTimeStamp) OVER (PARTITION by ScheduledID ORDER BY ModifiedTimeStamp)
FROM schedules
) a

如果您使用的是早于2012的版本,则可以使用ROW_NUMBER()功能和自加入,如下所示:

-- 2008 version
SELECT 
    curr.ScheduledID, curr.StartTime, curr.EndTime, curr.ModifiedTimeStamp,
    CASE 
       WHEN prev.rn IS NULL THEN 'Schedule created' 
       WHEN prev.StartTime <> curr.StartTime AND prev.EndTime = curr.EndTime  
          THEN 'Start Time Modified FROM ' + prev.StartTime + ' to ' + curr.StartTime 
       WHEN prev.StartTime <> curr.StartTime AND prev.EndTime <> curr.EndTime AND next.rn IS NOT NULL 
          THEN 'Start Time Modified FROM ' + prev.StartTime + ' to ' + curr.StartTime 
          + ', End Time Modified FROM ' + prev.EndTime + ' to ' + curr.EndTime 
       WHEN prev.EndTime <> curr.EndTime AND next.rn IS NOT NULL 
          THEN 'End Time Modified FROM ' + prev.EndTime + ' to ' + curr.EndTime 
       WHEN next.rn IS NULL THEN 'Current schedule' 
    END as 'Action Type'
FROM (
    SELECT ScheduledID, StartTime, EndTime, ModifiedTimeStamp, ROW_NUMBER() OVER (PARTITION by ScheduledID ORDER BY ModifiedTimeStamp) rn
    FROM schedules) curr
LEFT JOIN (
    SELECT ScheduledID, StartTime, EndTime, ModifiedTimeStamp, ROW_NUMBER() OVER (PARTITION by ScheduledID ORDER BY ModifiedTimeStamp) rn
    FROM schedules
    ) prev on curr.rn = prev.rn + 1 AND prev.ScheduledID = curr.ScheduledID
LEFT JOIN (
    SELECT ScheduledID, StartTime, EndTime, ModifiedTimeStamp, ROW_NUMBER() OVER (PARTITION by ScheduledID ORDER BY ModifiedTimeStamp) rn
    FROM schedules
    ) next on curr.rn = next.rn - 1 AND curr.ScheduledID = next.ScheduledID
ORDER BY curr.rn

Sample SQL Fiddle这两个版本。

答案 1 :(得分:2)

;
WITH    cte
          AS ( SELECT   ROW_NUMBER() OVER ( PARTITION BY ScheduledID ORDER BY modifiedtimestamp ) AS RN ,
                        ScheduledID ,
                        StartTime ,
                        EndTime ,
                        ModifiedTimeStamp
               FROM     schedules
             ),
        laglead2008
          AS ( SELECT   a.ScheduledID ,
                        b.StartTime AS prevStartTime ,
                        a.StartTime ,
                        c.StartTime AS nextStartTime ,
                        b.EndTime AS prevEndtime ,
                        a.EndTime ,
                        c.EndTime AS nextEndTime ,
                        b.modifiedtimestamp AS prevts ,
                        a.ModifiedTimeStamp ,
                        c.modifiedtimestamp AS nextts
               FROM     cte AS a
                        LEFT JOIN cte AS b ON ( a.RN - 1 ) = b.RN
                                              AND b.ScheduledID = a.ScheduledID
                        LEFT JOIN cte AS c ON ( a.RN + 1 ) = c.RN
                                              AND a.ScheduledID = b.ScheduledID
             )
    SELECT  ScheduledID ,
            StartTime ,
            EndTime ,
            ModifiedTimeStamp ,
            CASE WHEN prevts IS NULL THEN 'Schedule created'
                 WHEN prevStartTime <> StartTime
                      AND prevEndtime = EndTime
                      AND nextts IS NOT NULL
                 THEN 'Start Time Modified from ' + prevStartTime + ' to '
                      + StartTime
                 WHEN prevStartTime <> StartTime
                      AND prevEndtime <> EndTime
                      AND nextts IS NOT NULL
                 THEN 'Start Time Modified from ' + prevStartTime + ' to '
                      + StartTime + ', End Time Modified from ' + prevEndtime
                      + ' to ' + EndTime
                 WHEN prevStartTime = StartTime
                      AND prevEndtime <> EndTime
                      AND nextts IS NOT NULL
                 THEN 'End Time Modified from ' + prevEndtime + ' to '
                      + EndTime
                 WHEN nextts IS NULL THEN 'Current Schedule'
            END AS 'Action Type'
    FROM    laglead2008
相关问题