如何基于活动起止日期使用SQL统计每日活动数量?
基于活动起止日期统计每日活跃唯一活动数量的SQL实现
需求
统计每日处于活跃状态的唯一活动数量,活跃状态定义为日期在活动的起止日期之间(含起止日)。
输入表(表名:campaigns)
| Campaign name | Start date | End date |
|---|---|---|
| Campaign A | 2022-07-10 | 2022-09-25 |
| Campaign B | 2022-08-06 | 2022-10-07 |
| Campaign C | 2022-07-30 | 2022-09-10 |
| Campaign D | 2022-08-26 | 2022-10-24 |
| Campaign E | 2022-07-17 | 2022-09-29 |
| Campaign F | 2022-08-24 | 2022-09-12 |
| Campaign G | 2022-08-11 | 2022-10-24 |
| Campaign H | 2022-08-26 | 2022-11-22 |
| Campaign I | 2022-08-29 | 2022-09-25 |
| Campaign J | 2022-08-21 | 2022-11-15 |
| Campaign K | 2022-07-20 | 2022-09-18 |
| Campaign L | 2022-07-31 | 2022-11-20 |
| Campaign M | 2022-08-17 | 2022-10-10 |
| Campaign N | 2022-07-27 | 2022-09-07 |
| Campaign O | 2022-07-29 | 2022-09-26 |
| Campaign P | 2022-07-06 | 2022-09-15 |
| Campaign Q | 2022-07-16 | 2022-09-22 |
期望输出
| Date | Count unique campaigns |
|---|---|
| 2022-07-02 | 17 |
| 2022-07-03 | 47 |
| 2022-07-04 | 5 |
| 2022-07-05 | 5 |
| 2022-07-06 | 25 |
| 2022-07-07 | 27 |
| 2022-07-08 | 17 |
| 2022-07-09 | 58 |
| 2022-07-10 | 23 |
| 2022-07-11 | 53 |
| 2022-07-12 | 18 |
| 2022-07-13 | 29 |
| 2022-07-14 | 52 |
| 2022-07-15 | 7 |
| 2022-07-16 | 17 |
| 2022-07-17 | 37 |
| 2022-07-18 | 33 |
SQL实现方案
要实现这个需求,核心步骤是:
- 生成覆盖目标日期范围的连续日期序列;
- 将日期序列与活动表关联,筛选出每个日期处于活跃期的活动;
- 按日期分组,统计唯一活动的数量。
下面是不同主流数据库的具体实现代码:
PostgreSQL
-- 生成2022-07-02到2022-07-18的连续日期 WITH date_series AS ( SELECT generate_series( '2022-07-02'::DATE, '2022-07-18'::DATE, '1 day'::INTERVAL ) AS date ), active_campaigns AS ( SELECT ds.date::DATE, c."Campaign name" FROM date_series ds LEFT JOIN campaigns c ON ds.date BETWEEN c."Start date" AND c."End date" ) SELECT date AS "Date", COUNT(DISTINCT "Campaign name") AS "Count unique campaigns" FROM active_campaigns GROUP BY date ORDER BY date;
MySQL 8.0+
-- 递归生成连续日期序列 WITH RECURSIVE date_series AS ( SELECT '2022-07-02' AS date UNION ALL SELECT DATE_ADD(date, INTERVAL 1 DAY) FROM date_series WHERE date < '2022-07-18' ), active_campaigns AS ( SELECT ds.date, c.`Campaign name` FROM date_series ds LEFT JOIN campaigns c ON ds.date BETWEEN c.`Start date` AND c.`End date` ) SELECT date AS `Date`, COUNT(DISTINCT `Campaign name`) AS `Count unique campaigns` FROM active_campaigns GROUP BY date ORDER BY date;
SQL Server
-- 递归生成连续日期序列 WITH date_series AS ( SELECT CAST('2022-07-02' AS DATE) AS date UNION ALL SELECT DATEADD(DAY, 1, date) FROM date_series WHERE date < CAST('2022-07-18' AS DATE) ), active_campaigns AS ( SELECT ds.date, c.[Campaign name] FROM date_series ds LEFT JOIN campaigns c ON ds.date BETWEEN c.[Start date] AND c.[End date] ) SELECT date AS [Date], COUNT(DISTINCT [Campaign name]) AS [Count unique campaigns] FROM active_campaigns GROUP BY date ORDER BY date OPTION (MAXRECURSION 0); -- 解除递归层数限制,避免默认100层的限制
内容的提问来源于stack exchange,提问作者Dulu
相关产品推荐
相关产品推荐

