2015-09-28 175 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年及以上 –