在 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 中查找非连续日期的主要内容,如果未能解决你的问题,请参考以下文章