在星型模式日期表中查找缺少的日期

时间:2019-06-10 14:39:53

标签: sql sql-server dimension

我有一个日期维度表。它从1900-01-01开始,包括每天直到2199-12-31的每一天。我需要找到它错过任何日期。

我在互联网上尝试了大多数的查询。我对sql的理解不足以将查询分开理解。另外,我没有写临时表的权限(正在处理临时表),因此这阻碍了某些工作。

这是我尝试过的一个。我的列名是ShortDate。我也尝试比较了一列longdate,但没有尝试。表名是dimDate。

   {
    SELECT t1.ShortDate AS startOfGap, MIN(t2.ShortDate) AS endOfGap  
       FROM  
       (SELECT ShortDate = ShortDate + 1  FROM sampleDates tbl1  
          WHERE NOT EXISTS(SELECT * FROM [Shared].[dimDates] tbl2  
                          WHERE tbl2.ShortDate = tbl1.ShortDate + 1) 
          AND ShortDate <> (SELECT MAX(ShortDate) FROM [Shared].[dimDates])) 
    t1 
       INNER JOIN  
       (SELECT ShortDate = ShortDate – 1  FROM [Shared].[dimDates] tbl1  
          WHERE NOT EXISTS(SELECT * FROM [Shared].[dimDates] tbl2  
                              WHERE tbl1.theDate = tbl2.theDate + 1) 
              AND ShortDate <> (SELECT MIN(ShortDate) FROM [Shared]. 
   [dimDates])) t2  
           ON t1.ShortDate <= t2.ShortDate 
           GROUP BY t1.ShortDate;
        }

我尝试的每个查询都会出现很多错误。不幸的是,我的逻辑还不足以理解该查询应包含的内容

我尝试过这个:

SELECT  TOP 1
        DateShort + 1
FROM   [Shared].[dimDates] mo
WHERE   NOT EXISTS
        (
        SELECT  NULL
        FROM    [Shared].[dimDates] mi 
        WHERE   mi.DateShort = mo.DateShort + 1
        )
ORDER BY DateShort

但是出现错误,指出“将nvarchar值'2029-10-02'转换为数据类型int时转换失败

2 个答案:

答案 0 :(得分:3)

自联接可以与datediff结合使用,以识别缺少日期的间隔。您会明白的。

 declare @test table (yourdate datetime);
 insert into @test
 values 
 ('2019-01-01'),
 ('2019-01-02'),
 ('2019-01-03'),
 ('2019-01-04'),
 ('2019-01-05'),
 ('2019-01-07')

 select t1.yourdate [firstdate], t2.yourdate [next date], 
 case when datediff(d,t1.yourdate,t2.yourdate) > 1 then 'flag' else 'ok' end [dayflag]
 from
 (
 select yourdate, row_number() over (order by yourdate) seq
 from @test
 )t1
 left join (select yourdate, row_number() over (order by yourdate) seq from @test) t2
 ON t1.seq = t2.seq - 1

答案 1 :(得分:1)

只需使用lead()

select sd.*
from (select sd.*, lead(shortdate) over (order by shortdate) as next_shortdate
      from sampleDates sd
     ) sd
where next_shortdate <> dateadd(day, 1, shortdate);

在周期结束时,这不会返回缺少日期的字符串。您可以使用以下方法解决此问题:

where next_shortdate <> dateadd(day, 1, shortdate) or
      (next_shortdate is null and shortdate < '2199-12-31'

您也可以使用join进行此操作:

select sd.*  -- the day before each group of missing dates
from sampleDates sd left join
     sampleDate sd_next
     on sd_next.shortdate = dateadd(day, 1, shortdate)
where sd_next.shortdate is null;

此版本将返回表中的最后一个日期,因此您可能需要添加:

where sd.shortdate <  '2199-12-31'