将 SQL 中的连续日期算作一个实例
Count consecutive dates in SQL as one instance
我想计算日期,但将连续的日期计为一个实例。在下面的示例 table 中,09/28/2013
和 09/29/2013
是连续的,因此它们算作一个实例。
user_id date
------ ------
ABC123 09/28/2013
ABC123 09/29/2013
ABC123 09/30/2013
ABC123 10/01/2013
输出:
user_id date_count
------ ------
ABC123 3
这取自 Sean Lange comment. His link (HERE) 正好符合您的需要。 link 的最终代码是...
WITH
cteGroupedDates AS
( --=== Find the unique dates and assign them to a group.
-- The group looks like a date but the date means nothing except that adjacent
-- dates will be a part of the same group.
SELECT UniqueDate = SomeDate,
DateGroup = DATEADD(dd, - ROW_NUMBER() OVER (ORDER BY SomeDate), SomeDate)
FROM #MyHead
GROUP BY SomeDate
)
--===== Now, if we find the MIN and MAX date for each DateGroup, we'll have the
-- Start and End dates of each group of contiguous daes. While we're at it,
-- we can also figure out how many days are in each range of days.
SELECT StartDate = MIN(UniqueDate),
EndDate = MAX(UniqueDate),
Days = DATEDIFF(dd,MIN(UniqueDate),MAX(UniqueDate))+1
FROM cteGroupedDates
GROUP BY DateGroup
ORDER BY StartDate
;
进行一些名称更改以尝试使其更易于理解...
WITH
dateGroup AS
( --This is used to distinguish the different continuous sets of dates
SELECT UniqueDate = date,
DateGroup = DATEADD(dd, - ROW_NUMBER() OVER (ORDER BY date), date)
FROM userdate
GROUP BY date
)
--Using dateGroup to get the groups of dates we can utilize it to get the count for them
SELECT StartDate = MIN(UniqueDate),
EndDate = MAX(UniqueDate),
Days = DATEDIFF(dd,MIN(UniqueDate),MAX(UniqueDate))+1,
u.user_id
FROM dateGroup JOIN userdate u ON u.date = UniqueDate
GROUP BY DateGroup, u.user_id
ORDER BY StartDate
;
我在 FROM dateCount
后面添加了 JOIN userdate u ON u.date = UniqueDate
以获取用户 ID。还将 u.user_id
添加到分组依据。不会工作,因为 u.user_id
在 SELECT 中(需要 GROUP BY 中 SELECT 中的信息)。
数据来自 Table:
证明:
------------编辑 1---------
我来猜猜你到底想要什么!
这就是我想到的。两个不同的查询都具有相同的结果。
第一次查询:
WITH
dateGroup AS
( --This is used to distinguish the different continuous sets of dates
SELECT UniqueDate = date,
DateGroup = DATEADD(dd, - ROW_NUMBER() OVER (ORDER BY date), date),
user_id
FROM userdate
GROUP BY date, user_id
),
userIDGroup AS
( --This is used to get the previous table that you saw in my original answer
SELECT COUNT(d.user_id) as 'Instances',
d.user_id
FROM dateGroup d
GROUP BY DateGroup, d.user_id
)
SELECT
COUNT(u.user_id) AS 'Instances',
u.user_id
FROM userIDGroup u
GROUP BY u.user_id
;
第二个查询(我也比较喜欢的那个):
WITH
dateGroup AS
( --This is used to distinguish the different continuous sets of dates
SELECT UniqueDate = date,
DateGroup = DATEADD(dd, - ROW_NUMBER() OVER (ORDER BY date), date),
user_id
FROM userdate
GROUP BY date, user_id
)
SELECT count(c.user_id) AS 'Instances', c.user_id
FROM
(
SELECT COUNT(d.user_id) as 'Instances',
d.user_id
FROM dateGroup d
GROUP BY DateGroup, d.user_id
) c GROUP BY c.user_id
;
证明:
调用您的来源 table users_and_dates
,下面将删除第二天也在数据集中的任何日期。
select t1.user_id,
count(*)
from users_and_dates t1
join users_and_dates t2
on t1.user_id=t2.user_id
and t1.date+1=t2.date
where t2.user_id is null
我想计算日期,但将连续的日期计为一个实例。在下面的示例 table 中,09/28/2013
和 09/29/2013
是连续的,因此它们算作一个实例。
user_id date
------ ------
ABC123 09/28/2013
ABC123 09/29/2013
ABC123 09/30/2013
ABC123 10/01/2013
输出:
user_id date_count
------ ------
ABC123 3
这取自 Sean Lange comment. His link (HERE) 正好符合您的需要。 link 的最终代码是...
WITH
cteGroupedDates AS
( --=== Find the unique dates and assign them to a group.
-- The group looks like a date but the date means nothing except that adjacent
-- dates will be a part of the same group.
SELECT UniqueDate = SomeDate,
DateGroup = DATEADD(dd, - ROW_NUMBER() OVER (ORDER BY SomeDate), SomeDate)
FROM #MyHead
GROUP BY SomeDate
)
--===== Now, if we find the MIN and MAX date for each DateGroup, we'll have the
-- Start and End dates of each group of contiguous daes. While we're at it,
-- we can also figure out how many days are in each range of days.
SELECT StartDate = MIN(UniqueDate),
EndDate = MAX(UniqueDate),
Days = DATEDIFF(dd,MIN(UniqueDate),MAX(UniqueDate))+1
FROM cteGroupedDates
GROUP BY DateGroup
ORDER BY StartDate
;
进行一些名称更改以尝试使其更易于理解...
WITH
dateGroup AS
( --This is used to distinguish the different continuous sets of dates
SELECT UniqueDate = date,
DateGroup = DATEADD(dd, - ROW_NUMBER() OVER (ORDER BY date), date)
FROM userdate
GROUP BY date
)
--Using dateGroup to get the groups of dates we can utilize it to get the count for them
SELECT StartDate = MIN(UniqueDate),
EndDate = MAX(UniqueDate),
Days = DATEDIFF(dd,MIN(UniqueDate),MAX(UniqueDate))+1,
u.user_id
FROM dateGroup JOIN userdate u ON u.date = UniqueDate
GROUP BY DateGroup, u.user_id
ORDER BY StartDate
;
我在 FROM dateCount
后面添加了 JOIN userdate u ON u.date = UniqueDate
以获取用户 ID。还将 u.user_id
添加到分组依据。不会工作,因为 u.user_id
在 SELECT 中(需要 GROUP BY 中 SELECT 中的信息)。
数据来自 Table:
证明:
------------编辑 1---------
我来猜猜你到底想要什么!
这就是我想到的。两个不同的查询都具有相同的结果。
第一次查询:
WITH
dateGroup AS
( --This is used to distinguish the different continuous sets of dates
SELECT UniqueDate = date,
DateGroup = DATEADD(dd, - ROW_NUMBER() OVER (ORDER BY date), date),
user_id
FROM userdate
GROUP BY date, user_id
),
userIDGroup AS
( --This is used to get the previous table that you saw in my original answer
SELECT COUNT(d.user_id) as 'Instances',
d.user_id
FROM dateGroup d
GROUP BY DateGroup, d.user_id
)
SELECT
COUNT(u.user_id) AS 'Instances',
u.user_id
FROM userIDGroup u
GROUP BY u.user_id
;
第二个查询(我也比较喜欢的那个):
WITH
dateGroup AS
( --This is used to distinguish the different continuous sets of dates
SELECT UniqueDate = date,
DateGroup = DATEADD(dd, - ROW_NUMBER() OVER (ORDER BY date), date),
user_id
FROM userdate
GROUP BY date, user_id
)
SELECT count(c.user_id) AS 'Instances', c.user_id
FROM
(
SELECT COUNT(d.user_id) as 'Instances',
d.user_id
FROM dateGroup d
GROUP BY DateGroup, d.user_id
) c GROUP BY c.user_id
;
证明:
调用您的来源 table users_and_dates
,下面将删除第二天也在数据集中的任何日期。
select t1.user_id,
count(*)
from users_and_dates t1
join users_and_dates t2
on t1.user_id=t2.user_id
and t1.date+1=t2.date
where t2.user_id is null