我现在编写了代码,该代码在每个Cust_ID
的每个期间内加入/检查请求期间的每个日期。但我认为应该是其他性能更高的解决方案。
是的,我做了作业,看到了很多答复,但是没有一个为我需要的问题提供明确的解决方案。感谢您的帮助。
这是一个测试数据,两个Cust
都有空白。如何显示有缺口的Cust(超过1天)
-- DROP TABLE #t
SELECT *
INTO #t
FROM
(SELECT
1 Cust_ID,
CAST('2003/10/14' AS DATE) StartDate,
CAST('2006/11/07' AS DATE) EndDate
UNION
SELECT 1, '2006/11/09', '2011/06/15'
UNION
SELECT 1, '2011/08/22', '2012/10/23'
UNION
SELECT 2, '2008/11/09', '2015/06/15'
UNION
SELECT 2, '2015/08/22', '2017/10/23'
UNION
SELECT 2, '2017/10/26', '2019/10/23'
) f -- SELECT * FROM #t
数据:
+---------+--------------+------------+
| Cust_ID | StartDate | EndDate |
+---------+--------------+------------+
| 1 | 2003-10-14 | 2006-11-07 |
| 1 | 2006-11-09 | 2011-06-15 |
| 1 | 2011-08-22 | 2012-10-23 |
| 2 | 2008-11-09 | 2015-06-15 |
| 2 | 2015-08-22 | 2017-10-23 |
| 2 | 2017-10-26 | 2019-10-23 |
+---------+--------------+------------+
===============================================================是我为简单起见就通过多步骤解决方案
-------------------------------------------------------------------------------- ---Set params for Period to check, and @BreakDays
DECLARE @Period_Start DATEtime = '2018-1-1',
@Period_End DATEtime = '2018-12-31',
@BreakDays INT = 0; -- 0 ==> no any single day break
IF OBJECT_ID( 'Tempdb..#Calendar') IS NOT NULL DROP TABLE #Calendar --- select * from #Calendar
IF OBJECT_ID( 'Tempdb..#t_all') IS NOT NULL DROP TABLE #t_all --- select * from #t_all
-------------------------------------------------------------------------------- Create DateDim for period
DECLARE @CalRows INT = ( SELECT DATEDIFF(DAY,@Period_Start ,@Period_End+1) ) --- set number of entries in #Calendar
SELECT TOP (DATEDIFF(DAY, @Period_Start, @Period_End + 1)) --- added 1 day to match number
DATEADD(dd,ROW_NUMBER() OVER (ORDER BY (SELECT NULL))-1,@Period_Start) dt --- select * from #Calendar
INTO #Calendar
FROM sys.all_columns sc1, sys.all_columns sc2; --- drop table #Calendar
SELECT * INTO #t_all FROM (
SELECT 1 Cust_ID, CAST('2003/10/14' AS DATE) StartDate, CAST('2006/11/07' AS DATE) EndDate UNION
SELECT 1, '2006/11/09' , '2011/06/15' union
SELECT 1, '2011/08/22' , '2012/10/23' union
SELECT 2, '2008/11/09' , '2015/06/15' union
SELECT 2, '2015/08/22' , '2017/10/23' UNION
SELECT 2, '2017/10/26' , '2019/10/23' ) f -- SELECT * FROM #t
WHERE 1=1
-- AND StartDate <= @Period_End -- end of period to search
-- AND EndDate >= @Period_Start -- Start of period to search
IF OBJECT_ID( 'Tempdb..#result') IS NOT NULL DROP TABLE #result -- SELECT top 100 * from #result
------------------------------------------------------------------ final step join to each date and verify
;with cte as (
SELECT t.*, c.dt
FROM #t_all t
join #Calendar c on c.dt between t.StartDate and t.EndDate
)
SELECT Cust_ID, count(Distinct dt) DDin, @CalRows - COUNT(Distinct dt) DDshort, @Period_Start Period_Start , @Period_End Period_End
INTO #result
FROM cte
group by Cust_ID
-- Having @CalRows - COUNT(Distinct dt) <= @BreakDays --184
SELECT * FROM #result WHERE DDShort >= @BreakDays
答案 0 :(得分:0)
我将答案完全基于您问题的标题,因为细节对我而言毫无意义。如果您要查找记录之间的日期间隔,VAR
是您的朋友-它从上一条记录中检索值。
Lag()
将导致
SELECT Cust_ID, StartDate, EndDate,
DATEDIFF(day, LAG(EndDate) OVER (PARTITION BY Cust_ID ORDER BY EndDate), StartDate)
AS GapInDays
FROM Table_1