按年份区间、专科及地区统计客户总数的SQL查询需求
问题描述
我有一个存储客户信息的customers表,表结构及示例数据如下:
| id | dateInscription | specialite | dept |
|---|---|---|---|
| 1 | 2018-04-09 | Anesthesiology | 75 |
| 2 | 2004-02-16 | Neurology | 62 |
| 3 | 1999-01-01 | Pathology | 34 |
| 4 | 2016-05-13 | Family medicine | 59 |
我需要按年份区间、specialite(专科)、dept(地区)统计客户总数。目前已实现按单一年份统计的SQL查询如下:
SELECT YEAR(dateInscription) as 'Annee_inscription', a.specialite, a.dept as 'Departement', COUNT(a.id) as 'NOMBRE_PS' FROM customers a WHERE YEAR(dateInscription) IN(2013, 2015, 2017, 2019, 2021) AND a.specialite IN ('ANATOMIE ET CYTOLOGIE PATHOLOGIQUES', 'ANESTHESIE-REANIMATION', 'BIOLOGIE MEDICALE', 'CARDIOLOGIE/PATHOLOGIE CARDIO-VASCULAIRE') GROUP BY Annee_inscription, a.specialite , Departement ORDER BY Annee_inscription ASC, a.specialite ASC, Departement ASC
期望的输出格式如下:
| Year_range | specialite | dept | number_customer |
|---|---|---|---|
| 1999-2004 | Anesthesiology | 01 | 10 |
| 1999-2004 | Anesthesiology | 02 | 13 |
| 1999-2004 | Anesthesiology | 03 | 25 |
| ... | ... | ... | .... |
| 1999-2004 | Family medicine | 01 | 124 |
| 1999-2004 | Family medicine | 02 | 514 |
| 1999-2004 | Family medicine | 03 | 1284 |
| ... | ... | ... | .... |
| 1999-2006 | Anesthesiology | 01 | 15 |
| 1999-2006 | Anesthesiology | 02 | 17 |
| 1999-2006 | Anesthesiology | 03 | 29 |
| ... | ... | ... | .... |
我尝试过用CASE语句分组但没得到理想结果,且没有该数据库的写入权限,求可行的解决方案。
解决方案
方法1:使用CASE语句定义固定年份区间
如果你的年份区间是固定的(比如示例中的1999-2004、1999-2006等),可以直接用CASE把每个客户的注册年份映射到对应的区间,再分组统计:
SELECT CASE WHEN YEAR(dateInscription) BETWEEN 1999 AND 2004 THEN '1999-2004' WHEN YEAR(dateInscription) BETWEEN 1999 AND 2006 THEN '1999-2006' -- 可根据需求添加更多区间 ELSE '其他' END AS Year_range, specialite, LPAD(dept, 2, '0') AS dept, -- 补零格式化地区编码,根据数据库调整函数 COUNT(id) AS number_customer FROM customers -- 保留需要的专科筛选条件 WHERE specialite IN ('ANATOMIE ET CYTOLOGIE PATHOLOGIQUES', 'ANESTHESIE-REANIMATION', 'BIOLOGIE MEDICALE', 'CARDIOLOGIE/PATHOLOGIE CARDIO-VASCULAIRE') GROUP BY Year_range, specialite, dept ORDER BY Year_range, specialite, dept;
注意:如果同一个年份属于多个区间(比如2004同时属于1999-2004和1999-2006),该方法会让对应客户被统计到多个区间中,符合你期望的重复统计逻辑。
方法2:用CTE生成年份区间列表(适合动态区间)
如果需要更灵活的区间定义,可通过CTE(公共表表达式)生成所有需要统计的区间,再关联原表统计:
WITH year_ranges AS ( SELECT '1999-2004' AS Year_range, 1999 AS start_year, 2004 AS end_year UNION ALL SELECT '1999-2006' AS Year_range, 1999 AS start_year, 2006 AS end_year -- 添加更多区间 ) SELECT yr.Year_range, c.specialite, LPAD(c.dept, 2, '0') AS dept, -- 补零格式化地区编码 COUNT(c.id) AS number_customer FROM year_ranges yr LEFT JOIN customers c ON YEAR(c.dateInscription) BETWEEN yr.start_year AND yr.end_year WHERE c.specialite IN ('ANATOMIE ET CYTOLOGIE PATHOLOGIQUES', 'ANESTHESIE-REANIMATION', 'BIOLOGIE MEDICALE', 'CARDIOLOGIE/PATHOLOGIE CARDIO-VASCULAIRE') GROUP BY yr.Year_range, c.specialite, c.dept ORDER BY yr.Year_range, c.specialite, c.dept;
这种方法的优势是区间定义集中在CTE里,修改起来更方便,且同样能实现同一客户在多个区间被统计的效果。
地区编码补零函数说明
不同数据库的补零函数略有差异,可根据实际情况替换:
- MySQL/MariaDB:
LPAD(dept, 2, '0') - PostgreSQL:
LPAD(dept::text, 2, '0') - SQL Server:
RIGHT('00' + CAST(dept AS VARCHAR(2)), 2)
内容的提问来源于stack exchange,提问作者D3m3t05
相关产品推荐
相关产品推荐

