2017-06-02 286 views
1

enter image description here如何獲得其匹配標準

我可以通過使用while循環,但由於原來的表有成千上萬條記錄,性能非常慢獲得所需的輸出日期範圍。

如何使用通用表達式得到期望的結果?

謝謝。

+0

的SQL Server的哪個版本? – Shawn

+0

@Shawn其Microsoft SQL Server 2008(SP4) – Ram

回答

1

這將產生所需的結果。不像戈登那麼優雅,但它確實可以彌補日期和重複日期。

如果您有日曆/提示表,則可以刪除cte邏輯。

Declare @YourTable Table ([AsOfDate] Date,[SecurityID] varchar(50),[IsHeld] bit) 
Insert Into @YourTable Values 
('2017-05-19','S1',1) 
,('2017-05-20','S1',1) 
,('2017-05-21','S1',1) 
,('2017-05-22','S1',1) 
,('2017-05-23','S1',0) 
,('2017-05-24','S1',0) 
,('2017-05-25','S1',0) 
,('2017-05-26','S1',1) 
,('2017-05-27','S1',1) 
,('2017-05-28','S1',1) 
,('2017-05-29','S1',0) 
,('2017-05-30','S1',0) 
,('2017-05-31','S1',1) 

;with cte1 as (Select D1=min(AsOfDate),D2=max(AsOfDate) From @YourTable) 
    ,cte2 as (
       Select Top (DateDiff(DAY,(Select D1 from cte1),(Select D2 from cte1))+1) 
         D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),(Select D1 from cte1)) 
         ,R=Row_Number() over (Order By (Select Null)) 
       From master..spt_values n1,master..spt_values n2 
      ) 
Select [SecurityID] 
     ,[StartDate] = min(D) 
     ,[EndDate] = max(D) 
From (
     Select *,Grp = dense_rank() over (partition by securityId order by asofdate)-R 
     From @YourTable A 
     Join cte2 B on AsOfDate=B.D 
     Where IsHeld=1 
    ) A 
Group By [SecurityID],Grp 
Order By min(D) 

返回

SecurityID  StartDate EndDate 
S1    2017-05-19 2017-05-22 
S1    2017-05-26 2017-05-28 
S1    2017-05-31 2017-05-31 
+0

謝謝John的幫助。 – Ram

+1

@Ram高興地幫助。 –

1

這是間隙和孤島問題的變體。在這種情況下,你可以使用日期計算與鄰近的日期來計算行:

select securityId, isheld, min(asofdate), max(asofdate) 
from (select t.*, 
       datediff(day, 
         - row_number() over (partition by securityId, isheld 
              order by asofdate 
              ), 
         asofdate) as grp 
     from t 
    ) t 
group by grp, securityId, isheld; 

注:這是假定的日期是連續的,沒有重複。該查詢可以修改以考慮這些因素。

基本思想是,如果你有一個一天增加一個日的序列,那麼你可以減去一系列值並得到一個常數。這就是grp是。剩下的只是聚合。

相關問題