【发布时间】:2016-02-29 16:55:37
【问题描述】:
我想搜索一个 SQL 表并找到两个连续缺失的日期。
例如,人 1 在第 1 天和第 2 天插入“日记”条目,错过了第 3 天和第 4 天,并在第 5 天输入了一个条目。
我没有发布代码,因为我完全不知道该怎么做。
谢谢!
【问题讨论】:
-
问题 - 如果他们错过了三天,您想看到两个不同的两天间隔吗?还是三天的差距?
我想搜索一个 SQL 表并找到两个连续缺失的日期。
例如,人 1 在第 1 天和第 2 天插入“日记”条目,错过了第 3 天和第 4 天,并在第 5 天输入了一个条目。
我没有发布代码,因为我完全不知道该怎么做。
谢谢!
【问题讨论】:
这使用 LEVEL 聚合来构建从第一个条目到最后一个条目的日历日期列表,然后使用 LAG() 检查给定日期与前一个日期,然后检查这些日期是否都没有关联条目找出这两天的差距:
With diary as (
select to_date('01/01/2016','dd/mm/yyyy') entry_dt from dual union all
select to_date('02/01/2016','dd/mm/yyyy') entry_dt from dual union all
select to_date('04/01/2016','dd/mm/yyyy') entry_dt from dual union all
--leave two day gap of 5th and 6th
select to_date('07/01/2016','dd/mm/yyyy') entry_dt from dual union all
select to_date('08/01/2016','dd/mm/yyyy') entry_dt from dual union all
select to_date('10/01/2016','dd/mm/yyyy') entry_dt from dual )
select calendar_dt -1, calendar_dt
FROM (
select calendar_dt, entry_dt, lag(entry_dt) over (order by calendar_dt) prev_entry_dt
from diary
RIGHT OUTER JOIN (select min(entry_dt) + lvl as calendar_dt
FROM diary
,(select level lvl
from dual connect by level < (select max(entry_dt) - min(entry_dt)+1 from diary))
group by lvl) ON calendar_dt = entry_dt
order by calendar_dt
)
where entry_dt is null and prev_entry_dt is null
返回:
CALENDAR_DT-1, CALENDAR_DT
05/01/2016, 06/01/2016
我只是在构建日历以简化构建所有 2 天的间隔,就好像一个人请了三天假,这将是两个重叠的两天间隔(第 1-2 天和第 2-3 天)。如果您想要一个更简单的查询来输出两天或更长时间的任何间隔的起点和终点,那么以下方法可以工作:
With diary as (
select to_date('01/01/2016','dd/mm/yyyy') entry_dt from dual union all
select to_date('02/01/2016','dd/mm/yyyy') entry_dt from dual union all
select to_date('04/01/2016','dd/mm/yyyy') entry_dt from dual union all
select to_date('07/01/2016','dd/mm/yyyy') entry_dt from dual union all
select to_date('08/01/2016','dd/mm/yyyy') entry_dt from dual union all
select to_date('10/01/2016','dd/mm/yyyy') entry_dt from dual )
select prev_entry_dt +1 gap_start, entry_dt -1 gap_end
FROM (
select entry_dt, lag(entry_dt) over (order by entry_dt) prev_entry_dt
from diary
order by entry_dt
) where entry_dt - prev_entry_dt > 2
【讨论】:
我解决此问题的高级方法是从动态日期表中进行选择,使用整数计数器从当前 DateTime 中添加或减去,以获得未来或过去所需的尽可能多的日期,然后 LEFT 加入您的数据表到此,按日期排序并选择第一行,或 N 多个具有 NULL 连接的行。
所以你的数据最终是
DATE ENTRY_ID
---- -----
2016-01-01 1
2016-01-02 2
2016-01-03 NULL
2016-01-04 3
2016-01-05 4
2016-01-06 NULL
2016-01-07 NULL
2016-01-08 NULL
你可以从这个数据集中选择你需要的所有值
【讨论】:
Try this your problem looks like similar to this :-
Declare @temp Table(id int identity(1,1) not null,CDate smalldatetime ,val int)
insert into @temp select '10/2/2012',1
insert into @temp select '10/3/2012',1
insert into @temp select '10/5/2012',1
insert into @temp select '10/7/2012',2
insert into @temp select '10/9/2012',2
insert into @temp select '10/10/2012',2
insert into @temp select '10/13/2012',2
insert into @temp select '10/15/2012',2
DECLARE @startDate DATE= '10/01/2012'
DECLARE @endDate DATE= '10/15/2012'
SELECT t.Id, X.[Date],Val = COALESCE(t.val,0)
FROM
(SELECT [Date] = DATEADD(Day,Number,@startDate)
FROM master..spt_values
WHERE Type='P'
AND DATEADD(day,Number,@startDate) <= @endDate)X
LEFT JOIN @temp t
ON X.[Date] = t.CDate
Alternative you can try this :-
WITH dates AS (
SELECT CAST('2009-01-01' AS DATETIME) 'date'
UNION ALL
SELECT DATEADD(dd, 1, t.date)
FROM dates t
WHERE DATEADD(dd, 1, t.date) <= '2009-02-01')
SELECT t.eventid, d.date
FROM dates d
JOIN TABLE t ON d.date BETWEEN t.startdate AND t.enddate
【讨论】: