在 SQL Server 中查找非连续日期

Posted

技术标签:

【中文标题】在 SQL Server 中查找非连续日期【英文标题】:Find Non Consecutive date in SQL Server 【发布时间】:2016-10-26 10:34:46 【问题描述】:

我想找到两个连续日期之间的missing NON-consecutive dates

我正在发布我的 SQL 查询和临时表以找出结果。

但我没有得到正确的结果

这是我的 SQL 查询

  drop table #temp
  create table #temp(an varchar(20),dt date)
  insert into #temp   
  select    '2133783715'    ,   '2016-10-16'    union all
  select    '5107537880'    ,   '2016-10-15'    union all
  select    '6619324250'    ,   '2016-10-15'    union all
  select    '7146586717'    ,   '2016-10-15'    union all
  select    '7472381321'    ,   '2016-10-12'    union all
  select    '7472381321'    ,   '2016-10-13'    union all
  select    '7472381321'    ,   '2016-10-14'    union all
  select    '7472381321'    ,   '2016-10-24'    union all
  select    '8186056340'    ,   '2016-10-15'    union all
  select    '9099457123'    ,   '2016-10-12'    union all
  select    '9099457123'    ,   '2016-10-13'    union all
  select    '9099457123'    ,   '2016-10-14'    union all
  select    '9099457123'    ,   '2016-10-23'    union all
  select    '9099457123'    ,   '2016-11-01'    union all
  select    '9099457123'    ,   '2016-11-02'    union all
  select    '9099457123'    ,   '2016-11-03'    union all
  select    '9165074784'    ,   '2016-10-16'


drop table #final
SELECT an,MIN(dt) AS MinDate,MAX(dt) AS MaxDate, COUNT(*) AS ConsecutiveUsage
  --DateDiff(Day,LAG(MAX(dt)) OVER (partition by an ORDER BY an),MAX(dt)) nonusageDate
 into #final
  FROM(
  SELECT an,dt,
   DATEDIFF(D, ROW_NUMBER() OVER(partition by an ORDER BY dt),dt) AS Diff
   FROM  #temp c 
)P
GROUP BY an,diff 

select * from #final order by 1

an             MinDate      MaxDate     ConsecutiveUsage    
2133783715     2016-10-16   2016-10-16  1    
5107537880     2016-10-15   2016-10-15  1    
6619324250     2016-10-15   2016-10-15  1    
7146586717     2016-10-15   2016-10-15  1    
7472381321     2016-10-12   2016-10-14  3    
7472381321     2016-10-24   2016-10-24  1   
7472381321     2016-10-27   2016-10-28  1 
8186056340     2016-10-15   2016-10-15  1    
9099457123     2016-10-12   2016-10-14  3    
9099457123     2016-10-23   2016-10-23  1    
9165074784     2016-10-16   2016-10-16  1    

但我想要非使用日期的结果。

我想得到那些10天以来没有连续使用过的AN。

所以这里输出应该是这样的:-

  an           minusagesdate  maxusagedate        ConsecutiveNotUseddays     
  7472381321   2016-10-15     2016-10-23           9
  7472381321   2016-10-25     2016-10-26           2
  9099457123   2016-10-15     2016-10-22           8

所以我只想找出连续未使用的日期计数及其最小和最大日期。

【问题讨论】:

为什么是连续未使用的第 10 天和第 11 天?我看不出这些数字是从哪里来的。 我想要连续没有使用的日期。就像 an- 7472381321 最小日期 2016-10-12 和最大日期是 2016-10-14。之后,他于 2016 年 10 月 24 日开始使用。所以我不想要这样的使用日期 7472381321 mindate 2016-10-15 和 maxdate - 2016-10-23 和 count:8。 【参考方案1】:

试试这个:

  with ranked as (
  select f1.*, 
  ROW_NUMBER() over(partition by an order by dt) rang
  from #temp f1
  where exists
  (select * from #temp f2
   where f1.an=f2.an and datediff( day, f2.dt, f1.dt) >1
  )
  )
  select an, minusagesdate, maxusagesdate,  ConsecutiveNotUseddays
  from (
  select f1.*, 
  DATEADD(DAY,1, (select f2.dt from ranked f2 where f1.an=f2.an and f2.rang+1=f1.rang)) minusagesdate   ,
  DATEADD(DAY,-1, f1.dt) maxusagesdate  , 
  datediff( day, (select f2.dt from ranked f2 where f1.an=f2.an and f2.rang+1=f1.rang), f1.dt) - 1 ConsecutiveNotUseddays
  from ranked f1 
  ) tmp
  where tmp.ConsecutiveNotUseddays>0

或者像这样

  with ranked as (
  select f1.*, 
  ROW_NUMBER() over(partition by an order by dt) rang
  from #temp f1
  where exists
  (select * from #temp f2
  where f1.an=f2.an and datediff( day, f2.dt, f1.dt) >1
  )
  )
  select f1.an, 
  DATEADD(DAY,1, f3.dtbefore) minusagesdate   ,
  DATEADD(DAY,-1, f1.dt) maxusagesdate  , 
  datediff( day, f3.dtbefore, f1.dt) - 1 ConsecutiveNotUseddays
  from ranked f1 
    outer apply
    (
    select top 1 f2.dt as dtbefore from ranked f2 
    where f1.an=f2.an and f2.rang+1=f1.rang
    ) f3
  where datediff( day, f3.dtbefore, f1.dt) - 1>0 

【讨论】:

我想要连续的未使用日期。就像一个 - 7472381321 最小日期 2016-10-12 和最大日期是 2016-10-14。之后,他于 2016 年 10 月 24 日开始使用。所以我不想要这样的使用日期 7472381321 mindate 2016-10-15 和 maxdate - 2016-10-23 和 count:8。 我认为你的例子是错误的,但我已经修改了我的回复 我已经修改了我的优化,但你可以点击向上箭头然后;) 感谢您的回答。虽然我已经使用 SQL Server 的 LAG 分析窗口函数删除了内部子查询。【参考方案2】:

您似乎正在尝试计算每个an 的mindate 和maxdate 之间未使用的天数。如果是这种情况,那么这应该可以解决问题:

select an, min(dt) as min_dt, max(dt) as max_dt
     , count(distinct dt) as daysused --this counts each day used, but only once
     , datediff(day,min(dt),max(dt)) as totaldays --this is the total number of days between min and max date
     , datediff(day,min(dt),max(dt)) - count(distinct dt) as daysnotused
            --This takes total days - used days to give non-used days
from #temp c 
group by an
having datediff(day,min(dt),max(dt)) - count(distinct dt) >= 10

【讨论】:

我想要连续没有使用的日期。就像 an- 7472381321 最小日期 2016-10-12 和最大日期是 2016-10-14。之后,他于 2016 年 10 月 24 日开始使用。所以我不想要这样的使用日期 7472381321 mindate 2016-10-15 and maxdate - 2016-10-23 and count:8.【参考方案3】:

据我了解,您需要这个:

;WITH cte AS (
    SELECT  an,
            dt,
            ROW_NUMBER() OVER (PARTITION BY an ORDER BY dt) as rn
    FROM #temp
)

SELECT  c1.an,
        c1.dt MinDate,
        c2.dt MaxDate,
        DATEDIFF(day,c1.dt,c2.dt) as ConsecutiveNotUseddays
FROM cte c1
INNER JOIN cte c2
    ON c1.an = c2.an AND c1.rn = c2.rn-1
WHERE DATEDIFF(day,c1.dt,c2.dt) >= 10

输出:

an          MinDate     MaxDate     ConsecutiveNotUseddays
7472381321  2016-10-14  2016-10-24  10

对于9099457123,我在ConsecutiveNotUseddays 中有两行9。您可以检查删除 WHERE 语句的结果。

【讨论】:

【参考方案4】:

在任何较新版本的 SQL Server 上,这应该很容易:

with x as (
    select *, lag(dt) over(partition by an order by dt) dt_lag
    from #temp
)
select *, datediff(day, dt_lag, dt) 
from x 
where datediff(day, dt_lag, dt) >= 10

【讨论】:

我想要连续的未使用日期。就像一个 - 7472381321 最小日期 2016-10-12 和最大日期是 2016-10-14。之后,他于 2016 年 10 月 24 日开始使用。所以我不想要这样的使用日期 7472381321 mindate 2016-10-15 和 maxdate - 2016-10-23 和 count:8。 对不起,但正如其他人已经评论的那样,您的示例数据和您的叙述都与示例结果不匹配。

以上是关于在 SQL Server 中查找非连续日期的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server:查找学生在自定义日期内的连续缺勤计数

选择查询以连续查找最大日期

需要在 SQL Server 2008 中查找两个日期之间的日期

sql server 生成连续日期

在 SQL Server 中查找最近的日期

SQL Server连续日期 - 将多行汇总为连续的开始和结束日期行,而不包含CTE,循环,... s