SQL统计查询问题:按Subname统计Returned与Enforcement_date日期对比
修正SQL实现指定统计需求
原始数据表
| ID | Projectname | Subname | Exp_return_date | Returned | Enforcement_date |
|---|---|---|---|---|---|
| 1 | A | A-1 | 1-4-2023 | 28-1-2023 | |
| 2 | A | A-1 | 1-4-2023 | 01-05-2023 | |
| 3 | A | A-1 | 1-4-2023 | 28-4-2023 | |
| 4 | A | A-2 | 1-7-2023 | 10-8-2023 | 2-8-2023 |
| 5 | A | A-2 | 1-7-2023 | 28-6-2023 | |
| 6 | A | A-2 | 1-7-2023 | 2-8-2023 | |
| 7 | B | B-1 | 1-3-2023 | 04-04-2023 | 1-4-2023 |
| 8 | B | B-1 | 1-3-2023 | 02-03-2023 | |
| 9 | B | B-2 | 1-6-2023 | 28-5-2023 | |
| 10 | B | B-2 | 1-6-2023 | 3-6-2023 |
期望统计结果
| Project | Subname | ED | Count | <=exp_return_date | <enforcement_date | eforcement_date_+1_month | None |
|---|---|---|---|---|---|---|---|
| A | A-1 | 01-05-2023 | 3 | 1 (all before 01-04-2023) | 2 (all before 01-05-2023) | 2 (all before 01-06-2023) | 1 |
| A | A-2 | 02-08-2023 | 3 | 1 (all before 01-07-2023) | 1 (all before 02-08-2023) | 2 (all before 02-09-2023) | 1 |
| B | B-1 | 01-04-2023 | 2 | 0 (all before 01-03-2023) | 1 (all before 01-04-2023) | 2 (all before 01-05-2023) | 0 |
| B | B-2 | 2 | 1 (all before 01-06-2023) | 0 |
需求说明
- 按Project、Subname分组,每组取非空的Enforcement_date作为ED;
- 统计每组总条数Count;
- 统计Returned ≤ Exp_return_date的数量;
- 统计Returned < Enforcement_date的数量(需处理Enforcement_date为空的情况);
- 统计Returned < Enforcement_date+1个月的数量;
- 统计Returned为空的数量。
当前问题SQL
SELECT [Project], [Subname], MIN(Enforcement_date) as ‘ED’, COUNT(*) as 'Count', COUNT(case when Returned <= Exp_return_date then 1 else null end) as ‘<= Exp_return_date’, COUNT(case when Returned <= Enforcement_date then 1 else null end) as ‘< Enformcement_date’, -- didn’t works, Enforcement_date is not always entered. COUNT(case when Returned <= Enforcement_date+1month then 1 else null end) as ‘< Enformcement_date’, -- how can I calculated this? COUNT(case when Returned <> '' then 1 else null end) as ‘None’ FROM ******* GROUP BY [Project], [Subname]
问题点:
- 未处理Enforcement_date为空的场景,导致对应统计项错误;
- 未正确实现Enforcement_date加1个月的日期计算与对比。
修正后的SQL(SQL Server版本)
SELECT Projectname AS Project, Subname, MAX(Enforcement_date) AS ED, COUNT(*) AS Count, -- 统计Returned ≤ Exp_return_date的数量 COUNT(CASE WHEN TRY_CAST(Returned AS DATE) <= TRY_CAST(Exp_return_date AS DATE) THEN 1 END) AS '<=exp_return_date', -- 统计Returned < Enforcement_date,空ED时返回NULL CASE WHEN MAX(Enforcement_date) IS NOT NULL THEN COUNT(CASE WHEN TRY_CAST(Returned AS DATE) < TRY_CAST(MAX(Enforcement_date) OVER(PARTITION BY Projectname, Subname) AS DATE) THEN 1 END) ELSE NULL END AS '<enforcement_date', -- 统计Returned < Enforcement_date+1个月,空ED时返回NULL CASE WHEN MAX(Enforcement_date) IS NOT NULL THEN COUNT(CASE WHEN TRY_CAST(Returned AS DATE) < DATEADD(MONTH, 1, TRY_CAST(MAX(Enforcement_date) OVER(PARTITION BY Projectname, Subname) AS DATE)) THEN 1 END) ELSE NULL END AS 'eforncement_date_+1_month', -- 统计Returned为空的数量 COUNT(CASE WHEN Returned IS NULL OR Returned = '' THEN 1 END) AS 'None' FROM YourTableName -- 替换为实际表名 GROUP BY Projectname, Subname
关键修正说明
- ED字段获取:用
MAX(Enforcement_date)确保取到分组内非空的执行日期(同一组非空值一致,MAX/MIN均可); - 空值处理:通过
CASE WHEN MAX(Enforcement_date) IS NOT NULL判断,空ED时对应统计项返回NULL,匹配期望结果; - 日期计算:用
DATEADD(MONTH, 1, ...)实现加1个月的逻辑,不同数据库需调整函数:- MySQL:
DATE_ADD(MAX(Enforcement_date), INTERVAL 1 MONTH) - Oracle:
ADD_MONTHS(MAX(Enforcement_date), 1)
- MySQL:
- 日期转换:用
TRY_CAST(SQL Server)或对应数据库的日期转换函数,避免字符串格式错误导致查询失败; - None统计修正:原逻辑错误,改为统计Returned为空或空字符串的记录数。
内容的提问来源于stack exchange,提问作者Pas Cal
相关产品推荐
相关产品推荐

