2015-09-28 211 views
1

我需要一種方法來找出每組相同ID集的天數。例如,如果有兩行ID1,第一個日期是第一個日期,第二個日期是第四個日期,則1st的計算將爲9月4日 - 9月1日(因爲4日是ID1的下一個日期),而第4天的計算方法是今天(9月28日) - 9月4日(因爲第4天是ID1的最後日期,而ID1的第4天之後沒有更多日期)。我在下面列出了每列的計算公式。日期範圍的簡單SQL查詢

IDs Date   
ID1 09/01/2015  
ID1 09/04/2015 
ID2 09/04/2015  
ID2 09/09/2015 
ID2 09/15/2015 
ID3 09/09/2015 
ID4 09/15/2015 

IDs Date   Days  Formula... 
ID1 09/01/2015  3   Sept 4th - Sept 1st 
ID1 09/04/2015  22  Today - Sept 4th 
ID2 09/04/2015  5   Sept 9th - Sept 4th 
ID2 09/09/2015  6   Sept 15th - Sept 9th 
ID2 09/15/2015  13  Today - Sept 15th 
ID3 09/09/2015  19  Today - Sept 9th 
ID4 09/15/2015  13  Today - Sept 15th 
+0

我認爲您的預期輸出不正確。 'ID2'有3條記錄。 「ID2」的最後一條記錄應該是「ID3」嗎? –

+0

我不認爲這有什麼簡單的,我只是把它拉到代碼中去做。這不是SQL所擅長的。 – CargoMeister

+0

ID3不是ID2的最後一個記錄。每行都有自己的一組ID。 @Jonathan Leffler我試圖在rdlc報告中做到這一點,但我無法弄清楚這就是爲什麼我雖然每次用戶單擊報表並從表中獲取報表時都會運行查詢並將其轉儲到表中。 – user3314399

回答

3

你基本上是尋找lead()功能。而且,你沒有它,所以你必須即興創作。下面是使用cross apply的方法:

select t.*, 
     datediff(day, t.date, coalesce(n.date, getdate()) 
from table t outer apply 
    (select top 1 t2.date 
     from table t2 
     where t2.id = t.id and t2.date > t.date 
     order by t2.date 
    ) n; 

這應該與(id, date)指數合理的性能。

+0

SQL Server 2008上是否有'LEAD'? –

+0

@FelixPamittan。 。 。不,那是我爲什麼要交叉應用方法。 –

+0

@FelixPamittan,2012年推出,https://msdn.microsoft.com/en-us/library/hh213125.aspx –

1

可以使用ROW_NUMBERLEFT JOIN一起做到這一點:

SQL Fiddle

WITH Cte AS(
    SELECT *, 
    rn = ROW_NUMBER() OVER(PARTITION BY ID ORDER BY [Date]) 
    FROM tbl 
) 
SELECT 
    t1.*, 
    Days = DATEDIFF(DAY, t1.Date, ISNULL(t2.Date, GETDATE())) 
FROM Cte t1 
LEFT JOIN Cte t2 
    ON t1.ID = t2.ID 
    AND t1.rn = t2.rn - 1 
2

使用公共表表達式,你可以安排你的表與一個開始日期和結束日期爲每個ID記錄一個臨時視圖,就像這樣:http://sqlfiddle.com/#!3/af078/7

with t1 (id, dt, ndx) as (
    select id, dt, row_number() over (partition by id order by dt) 
    from id_dates 
) 
, 
t2 (id, startdt, enddt) as (
    select t1.id, t1.dt, coalesce(t2.dt, convert(date, getdate())) 
    from t1 
    left join t1 t2 
    on t2.id = t1.id 
    and t2.ndx = t1.ndx + 1 
) 
select * from t2 

確保使用的​​3210功能獲取最後一行的當前日期(否則它將從左連接中爲空)。

從那裏,它是一個使用datediff()功能的一個簡單的問題:http://sqlfiddle.com/#!3/af078/8

with t1 (id, dt, ndx) as (
    select id, dt, row_number() over (partition by id order by dt) 
    from id_dates 
) 
, 
t2 (id, startdt, enddt) as (
    select t1.id, t1.dt, coalesce(t2.dt, convert(date, getdate())) 
    from t1 
    left join t1 t2 
    on t2.id = t1.id 
    and t2.ndx = t1.ndx + 1 
) 
select id, startdt, datediff(day, startdt, enddt) as dtcount 
from t2 
1

這裏是工作的例子,你可以這樣做沒有任何連接。 只需使用Lead窗口功能即可。

--Here is your data 
DECLARE @Data TABLE(ID NVARCHAR(8),Date DATE) 
INSERT INTO @Data(ID,Date) 
VALUES 
('ID1','09/01/2015'), 
('ID1','09/04/2015'), 
('ID2','09/04/2015'), 
('ID2','09/09/2015'), 
('ID2','09/15/2015'), 
('ID3','09/09/2015'), 
('ID4','09/15/2015') 

--This is all you need, Assuming your using a version of SQL that supports LEAD!!! 
SELECT ID,DATEDIFF(D,Date,ISNULL(LEAD(Date) OVER(PARTITION BY ID ORDER BY Date),GETDATE())) 
FROM  @Data 
+0

你能檢查一下SQL Server 2008嗎? –

+0

LEAD不在2008 R2,在2012年及以上 –