使用CTE来实现一条查询丢失的数据行问题

问题描述:PricesDaily表存有每天的价格数据,基本上是每天一条(除去周末两天和法定节假日没有)。
        现在问题是其中(以ASXCode和Date来判断)某天的数据丢失,有啥方法找到丢失这天的数据(返回丢失的ASXCode和Date)。

PricesDaily原表数据如下:
ASXCode,Date,Price
-------------------------------------
AAA 1999-01-04 00:00:00 2.5000
AAA 1999-01-05 00:00:00 2.4200
AAA 1999-01-06 00:00:00 2.4500
AAA 1999-01-07 00:00:00 2.5100
AAA 1999-01-08 00:00:00 2.5700
AAA 1999-01-11 00:00:00 2.6200
AAA 1999-01-12 00:00:00 2.7400
AAA 1999-01-13 00:00:00 2.6300
AAA 1999-01-14 00:00:00 2.6400
AAA 1999-01-15 00:00:00 2.7200
AAA 1999-01-19 00:00:00 2.6400
AAB 2004-09-24 00:00:00 .8400
AAB 2004-09-27 00:00:00 .8400
AAB 2004-09-28 00:00:00 .8300
AAB 2004-09-29 00:00:00 .8400
AAB 2004-09-30 00:00:00 .8300
AAB 2004-10-01 00:00:00 .8300
AAB 2004-10-04 00:00:00 .8000
AAB 2004-10-05 00:00:00 .8300
AAB 2004-10-07 00:00:00 .8300
AAB 2004-10-08 00:00:00 .7900

-------
上面原表中,有啥方法可以查出丢失了两条(周末两天和法定节假日除外):
ASXCode = 'AAA',Date = '1999-01-18' 和 ASXCode = 'AAB',Date = '2004-10-06';
只要返回丢失的ASXCode和Date。

使用CTE解决方法:



use Test
Declare @1 Table(ASXCode char(3),Date datetime,Price money)
Insert Into @1 
Select 'AAA''1999-01-04 00:00:00'2.5000 Union All
Select 'AAA''1999-01-05 00:00:00'2.4200 Union All
Select 'AAA''1999-01-06 00:00:00'2.4500 Union All
Select 'AAA''1999-01-07 00:00:00'2.5100 Union All
Select 'AAA''1999-01-08 00:00:00'2.5700 Union All
Select 'AAA''1999-01-11 00:00:00'2.6200 Union All
Select 'AAA''1999-01-12 00:00:00'2.7400 Union All
Select 'AAA''1999-01-13 00:00:00'2.6300 Union All
Select 'AAA''1999-01-14 00:00:00'2.6400 Union All
Select 'AAA''1999-01-15 00:00:00'2.7200 Union All
Select 'AAA''1999-01-19 00:00:00'2.6400 Union All
Select 'AAB''2004-09-24 00:00:00', .8400 Union All
Select 'AAB''2004-09-27 00:00:00', .8400 Union All
Select 'AAB''2004-09-28 00:00:00', .8300 Union All
Select 'AAB''2004-09-29 00:00:00', .8400 Union All
Select 'AAB''2004-09-30 00:00:00', .8300 Union All
Select 'AAB''2004-10-01 00:00:00', .8300 Union All
Select 'AAB''2004-10-04 00:00:00', .8000 Union All
Select 'AAB''2004-10-05 00:00:00', .8300 Union All
Select 'AAB''2004-10-07 00:00:00', .8300 Union All
Select 'AAB''2004-10-08 00:00:00', .7900 

;
With T1
As
(
    
Select ASXCode,Startdate=Min(Date),EndDate=Max(Date)
    
From @1
    
Group By ASXCode

,T2
As
(
    
Select ASXCode,Date=Startdate
    
From T1
    
Union All
    
Select a.ASXCode,Date=a.Date+1
    
From T2 a,T1 b Where a.ASXCode=b.ASXCode And a.Date<b.EndDate
)
Select a.*
From T2 a
Left Outer Join @1 b On b.ASXCode=a.ASXCode And a.Date=b.Date
Where b.Date Is null And Datename(dw,a.date) Not In('星期六','星期日')
Option(Maxrecursion 0)
--其他假日条件可以自由加入

/*

(21 行受影响)
ASXCode Date
------- -----------------------
AAB     2004-10-06 00:00:00.000
AAA     1999-01-18 00:00:00.000

(2 行受影响)
*/

CTE默认可以递归100层,所以使用Option(Maxrecursion 0)参数,
CTE目前最大可以32767层,从我们现实考虑(Select 32767/365.0=89.772602)可以查询89年的数据,已经够用了呵呵。


原文地址:https://www.cnblogs.com/wghao/p/1203623.html