识别日期范围中的记录间隙

时间:2016-10-27 15:28:56

标签: sql-server tsql gaps-and-islands

问题:我想确定哪些记录每天没有两条记录。排名告诉我每天是否有第二条记录......

SELECT TR.tourid,
       TR.tourruntimestamp,
       TC.tourname,
       TC.tourfrequency,
       TC.unit,
       TC.division,
       RANK()
         OVER (
           PARTITION BY TR.tourid
           ORDER BY TR.tourruntimestamp) AS [Rank]
FROM   DBO.tbltourrun AS TR
       INNER JOIN DBO.tso_piml_tour_config AS TC
               ON TC.tourid = TR.tourid
WHERE  ( TC.tourfrequency = '2xDay' )
       AND ( TR.tourruntimestamp BETWEEN Dateadd(DAY, Datediff(DAY, 0, Getdate()) - 1, 0) AND Dateadd(DAY, Datediff(DAY, 0, Getdate()), 0) )  

ScreenShot of Results

3 个答案:

答案 0 :(得分:1)

更一般的答案。我不知道你想用几周,几个月等做什么。

select      *

from       (SELECT        TR.TourID, TR.TourRunTimeStamp, TC.tourName, TC.tourFrequency, TC.Unit, TC.Division
                         ,count(*) OVER (PARTITION BY TR.TourID) AS cnt
            FROM            dbo.tblTourRun AS TR INNER JOIN
                                     dbo.TSO_PIML_Tour_Config AS TC ON TC.tourID = TR.TourID
            WHERE           TR.TourRunTimeStamp  BETWEEN DATEADD(day, DATEDIFF(day, 0, GETDATE()) - 1, 0) AND DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0))
            ) t

where       cnt <> case TC.tourFrequency when '1xDay' then 1 when '2xDay' then 2 when '4xDay' then 4 end
;
select      *

from       (SELECT        TR.TourID, TR.TourRunTimeStamp, TC.tourName, TC.tourFrequency, TC.Unit, TC.Division, count(*) OVER (PARTITION BY TR.TourID) AS cnt
            FROM            dbo.tblTourRun AS TR INNER JOIN
                                     dbo.TSO_PIML_Tour_Config AS TC ON TC.tourID = TR.TourID
            WHERE        (TC.tourFrequency = '2xDay') AND (TR.TourRunTimeStamp  BETWEEN DATEADD(day, DATEDIFF(day, 0, GETDATE()) - 1, 0) AND DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0))
            ) t

where       cnt = 1
;

答案 1 :(得分:1)

下面是一个人为的例子,它可以让你朝着正确的方向前进。我使用一个由值组成的表来模拟您尝试使用的数据的形状(剥离与该示例无关的值)。

select a.TourId
     , b.TourDate
from (values
    (1, Convert(datetime2(0), N'2016-01-01 00:00:00'))
  , (1, Convert(datetime2(0), N'2016-01-01 04:00:00'))
  , (1, Convert(datetime2(0), N'2016-01-03 00:00:00'))
  , (1, Convert(datetime2(0), N'2016-01-04 00:00:00'))
  , (1, Convert(datetime2(0), N'2016-01-04 04:00:00'))
  , (1, Convert(datetime2(0), N'2016-01-05 00:00:00'))
  , (2, Convert(datetime2(0), N'2016-02-11 00:00:00'))
  , (2, Convert(datetime2(0), N'2016-02-11 18:00:00'))
  , (2, Convert(datetime2(0), N'2016-02-13 00:00:00'))
  , (2, Convert(datetime2(0), N'2016-02-14 00:00:00'))
  , (2, Convert(datetime2(0), N'2016-02-14 18:00:00'))
  , (2, Convert(datetime2(0), N'2016-02-15 00:00:00'))
) as a (TourId, TourRunTimeStamp)
cross apply (values(Convert(date, a.TourRunTimeStamp))) as b (TourDate)
group by a.TourId
       , b.TourDate
having Count(1) != 2; -- find ids with exactly two entries
-- having Count(1) in (2, 4); -- find ids with exactly two or four entries
-- having Count(1) % 2 = 0; -- find ids with an even number of entries

这里的逻辑很简单:将日期时间转换为日期(这是在APPLY子句中完成的,以便我们可以重用计算),在TourId + {{ 1}},计算记录数,并过滤掉所有没有等于2的计数的结果。

答案 2 :(得分:0)

  

最终SQL结果:
  在一些CTE或视图的帮助下,我能够使其正常工作。

  1. 查询1-游览在日期范围(昨天)
  2. 之间运行
  3. 查询2-摘要显示在Datestamp列上没有日期戳记为空的游览
  4. 查询3-错过巡视时的条件计数,因此我显示错过的路线为0
  5. `--Get All ToursRanYesterday 
    WITH toursranyesterday 
         AS (SELECT TR.tourid, 
                    TR.tourruntimestamp, 
                    TC.tourname, 
                    TC.division, 
                    TC.unit, 
                    TC.tourfrequency 
             FROM   dbo.tbltourrun AS TR 
                    INNER JOIN dbo.tso_piml_tour_config AS TC 
                            ON TC.tourid = TR.tourid 
             WHERE  ( TC.tourfrequency LIKE '%xDay%' ) 
                    AND ( TR.tourruntimestamp 
                          BETWEEN Dateadd(day, Datediff(day, 
                                       0,Getdate()) - 1, 0) 
                                                      AND 
                          Dateadd(day, Datediff(day, 
                                       0, Getdate()), 0) )), 
         --Get Summary of xDay Tours Ran with Missing Tours 
         toursummary 
         AS (SELECT TC.tourid, 
                    TC.division, 
                    TC.unit, 
                    TC.tourname, 
                    TC.tourfrequency, 
                    ( CASE 
                        WHEN EXISTS (SELECT * 
                                     FROM   toursranyesterday AS TY 
                                     WHERE  TC.tourid = TY.tourid) THEN 'NO' 
                        WHEN NOT EXISTS (SELECT * 
                                         FROM   toursranyesterday AS TY 
                                         WHERE  TC.tourid = TY.tourid) THEN 'YES' 
                      END ) AS Missed, 
                    TY.tourruntimestamp 
             FROM   dbo.tso_piml_tour_config AS TC 
                    FULL OUTER JOIN toursranyesterday AS TY 
                                 ON TY.tourid = TC.tourid 
             WHERE  ( TC.tourfrequency LIKE '%xDay%' )) 
    --Add Daily Tour Count when Missed = NO 
    SELECT TS.tourid, 
           TS.division, 
           TS.unit, 
           TS.tourname, 
           TS.tourfrequency, 
           TS.missed, 
           TS.tourruntimestamp, 
           Count(CASE 
                   WHEN missed = 'NO' THEN 1 
                   ELSE NULL 
                 END) 
             OVER ( 
               partition BY TS.tourid) AS [DailyTourCount] 
    FROM   toursummary AS TS 
    ORDER  BY TS.tourname `