我需要一种方法来查找每组相同ID设置的天数。例如,如果有两行ID1,第一个日期是第一个,第二个日期是第4个,第一个的计算将是9月4日 - 9月1日(因为第4个是ID1的下一个日期)和第四个的计算是今天(9月28日) - 9月4日(因为第4个是ID1的最后一个日期,ID1的第4个日期之后没有日期)。我在下面的旁边列出了计算每列的公式。
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 :(得分: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)
。
答案 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
确保使用coalesce
函数获取最后一行的当前日期(否则它将从左连接中为空)。
从那里开始,使用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
答案 2 :(得分:1)
您可以使用ROW_NUMBER
和LEFT JOIN
一起执行此操作:
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
答案 3 :(得分: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