SQLite:按分组统计日期差≤1年的记录占总条目数的比例
统计每组中日期差≤1年的记录占比解决方案
先把你的数据整理成清晰的表格:
| group | date1 | date2 |
|---|---|---|
| A | 2014-04-04 09:20:04.903 | 2015-05-04 09:20:04.903 |
| A | 2015-04-04 09:20:04.903 | 2015-03-04 09:20:04.903 |
| B | 2016-04-04 09:20:04.903 | None |
| B | 2016-07-04 09:20:04.903 | 2015-07-04 09:20:04.903 |
你的需求是:按group分组,计算每组中date1与date2日期差≤1年的记录数占该组总条目数的比例,规则是date2为空时视为不符合条件,date1不会为空。根据你给出的示例,两组最终占比都是50%,这个逻辑是完全正确的。
核心实现思路
- 给每条记录打"合格标签":判断是否满足
date2非空且date1和date2的日期差绝对值≤1年(因为date1可能比date2早或晚,比如A组第二条记录date1比date2晚,取绝对值能避免正负差的判断误差) - 按
group分组,统计每组的合格记录数和总记录数 - 用合格数除以总数得到占比,注意处理除法的精度问题(避免整数除法导致的0或1的错误结果)
示例SQL代码(以PostgreSQL为例)
SELECT "group", -- 统计符合条件的记录数 COUNT(CASE WHEN date2 IS NOT NULL AND ABS(EXTRACT(YEAR FROM AGE(date1, date2))) <= 1 THEN 1 END) AS valid_count, -- 统计每组总记录数 COUNT(*) AS total_count, -- 计算占比并转为百分比,保留两位小数 ROUND( COUNT(CASE WHEN date2 IS NOT NULL AND ABS(EXTRACT(YEAR FROM AGE(date1, date2))) <= 1 THEN 1 END)::NUMERIC / COUNT(*) * 100, 2 ) AS valid_ratio_percent FROM your_table_name -- 替换成你的实际表名 GROUP BY "group";
代码逻辑解释
CASE语句:只有当date2不为空,且两个日期的年份差绝对值≤1时,才会被计入valid_count,否则这条记录会被忽略(COUNT函数会自动跳过NULL值)::NUMERIC是把整数转换为数值类型,避免PostgreSQL中整数除法直接取整的问题(比如1/2会得到0,转换后能得到0.5)ROUND(...,2)是把百分比结果保留两位小数,让输出更直观美观
适配其他数据库(比如MySQL)
如果用MySQL,日期差的计算函数不一样,用TIMESTAMPDIFF来计算年份差,代码如下:
SELECT `group`, COUNT(CASE WHEN date2 IS NOT NULL AND ABS(TIMESTAMPDIFF(YEAR, date2, date1)) <= 1 THEN 1 END) AS valid_count, COUNT(*) AS total_count, ROUND( COUNT(CASE WHEN date2 IS NOT NULL AND ABS(TIMESTAMPDIFF(YEAR, date2, date1)) <= 1 THEN 1 END) / COUNT(*) * 100, 2 ) AS valid_ratio_percent FROM your_table_name GROUP BY `group`;
注意:group是SQL的关键字,所以需要用反引号(MySQL)或者双引号(PostgreSQL)包裹,避免语法错误。
内容的提问来源于stack exchange,提问作者Calvin77
相关产品推荐
相关产品推荐

