如何关联两个CTE并通过GROUP BY生成正确的汇总结果?
问题:关联两个CTE后统计列结果全为0,无法得到预期汇总表
背景说明
两个CTE派生自同一张表:
open_bridges:筛选条件为Structure Code IN ('F')gikl_all_strucs:筛选条件为Structure Code IN ('G','I','K','L')
open_bridges的前24行样本数据:
| 结构类型(Structure Type) | 建造年份(Year Built) | 结构代码(Structure Code) | 状态授予日期(Status Granted Date) |
|---|---|---|---|
| BRIDGE | 1958 | F | 12/6/2016 |
| TUNNEL | 1961 | L | 3/28/2022 |
| BRIDGE | 1999 | F | 1/9/2002 |
| RWALL | 1998 | I | 4/17/2000 |
| BRIDGE | 2014 | F | 11/7/2018 |
| BRIDGE | 2017 | G | 5/08/2020 |
| BRIDGE | 2012 | K | 1/9/2017 |
| RWALL | 2003 | F | 3/07/2007 |
| BRIDGE | 1999 | F | 2/24/2011 |
| BRIDGE | 2006 | K | 6/02/2017 |
| BRIDGE | 2008 | F | 9/24/2019 |
| TUNNEL | 2000 | F | 4/17/2016 |
| TUNNEL | 2011 | I | 11/7/2018 |
| BRIDGE | 2013 | G | 5/08/2020 |
| BRIDGE | 2017 | F | 1/9/2020 |
| RWALL | 2003 | F | 3/07/2005 |
| TUNNEL | 2011 | I | 11/7/2018 |
| BRIDGE | 2013 | G | 5/08/2020 |
| BRIDGE | 2017 | F | 1/9/2020 |
| RWALL | 2003 | F | 3/07/2005 |
| TUNNEL | 2016 | K | 12/5/2019 |
| RWALL | 2014 | F | 8/05/2016 |
| RWALL | 2015 | F | 1/9/2021 |
| BRIDGE | 2017 | K | 3/03/2022 |
单独查询的正确结果
查询1:统计各结构类型下建造年份≤对应年份的数量
SELECT oba.Structure_type, SUM(CASE WHEN oba.YEAR_BUILT<='2016' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2016, SUM(CASE WHEN oba.YEAR_BUILT<='2017' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2017, SUM(CASE WHEN oba.YEAR_BUILT<='2018' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2018, SUM(CASE WHEN oba.YEAR_BUILT<='2019' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2019, SUM(CASE WHEN oba.YEAR_BUILT<='2020' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2020, SUM(CASE WHEN oba.YEAR_BUILT<='2021' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2021, SUM(CASE WHEN oba.YEAR_BUILT<='2022' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2022, SUM(CASE WHEN oba.YEAR_BUILT<='2023' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2023 FROM open_bridges oba GROUP BY oba.structure_type ORDER BY oba.structure_type DESC
查询结果:
| 结构类型(Structure_type) | y2016 | y2017 | y2018 | y2019 | y2020 | y2021 | y2022 | y2023 |
|---|---|---|---|---|---|---|---|---|
| TUNNEL | 3 | 4 | 4 | 4 | 4 | 5 | 5 | 5 |
| RWALL | 5 | 5 | 6 | 6 | 6 | 6 | 6 | 6 |
| BRIDGE | 6 | 10 | 12 | 13 | 13 | 13 | 13 | 13 |
查询2:统计各结构类型下状态授予日期年份≥2016的数量
SELECT gika.Structure_type, SUM(CASE WHEN EXTRACT(YEAR FROM gika.status_granted_date) >='2016' THEN 1 ELSE 0 END) AS gik2016 FROM gikl_all_strucs gika GROUP BY gika.structure_type
查询结果:
| 结构类型(Structure_type) | gik2016 |
|---|---|
| BRIDGE | 13 |
| RWALL | 5 |
| TUNNEL | 4 |
关联查询的问题
尝试通过LEFT JOIN关联两个CTE并GROUP BY时,gik2016列全为0,使用的SQL语句如下:
SELECT oba.STructure_type, SUM(CASE WHEN oba.YEAR_BUILT<='2016' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2016, SUM(CASE WHEN EXTRACT(YEAR FROM gika.current_status_granted_date) >='2016' THEN 1 ELSE 0 END) AS gik2016, SUM(CASE WHEN oba.YEAR_BUILT<='2017' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2017, SUM(CASE WHEN oba.YEAR_BUILT<='2018' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2018, SUM(CASE WHEN oba.YEAR_BUILT<='2019' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2019, SUM(CASE WHEN oba.YEAR_BUILT<='2020' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2020, SUM(CASE WHEN oba.YEAR_BUILT<='2021' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2021, SUM(CASE WHEN oba.YEAR_BUILT<='2022' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2022, SUM(CASE WHEN oba.YEAR_BUILT<='2023' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2023 FROM open_bridges oba LEFT JOIN gikl_all_strucs gika ON oba.structure_type=gika.structure_type AND oba.structure_no=gika.structure_no AND oba.year_built=gika.year_built AND oba.structure_status_type_code=gika.structure_status_type_code GROUP BY oba.structure_type ORDER BY oba.structure_type DESC
预期汇总表:
| 结构类型(Structure_type) | y2016 | gik2016 | y2017 | y2018 | y2019 | y2020 | y2021 | y2022 | y2023 |
|---|---|---|---|---|---|---|---|---|---|
| TUNNEL | 3 | 4 | 4 | 4 | 4 | 4 | 5 | 5 | 5 |
| RWALL | 5 | 5 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
| BRIDGE | 6 | 13 | 10 | 12 | 13 | 13 | 13 | 13 | 13 |
修正方案
问题原因
- 关联条件过于严格:两个CTE的
Structure Code互斥(一个为F,一个为G/I/K/L),通过structure_no、year_built等字段关联不会有匹配数据,导致gika表字段全为NULL,SUM计算结果为0。 - 字段名错误:查询2使用
status_granted_date,但关联查询中误写为current_status_granted_date,字段不匹配。
修正后的SQL
WITH open_bridges_stats AS ( SELECT oba.Structure_type, SUM(CASE WHEN oba.YEAR_BUILT<='2016' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2016, SUM(CASE WHEN oba.YEAR_BUILT<='2017' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2017, SUM(CASE WHEN oba.YEAR_BUILT<='2018' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2018, SUM(CASE WHEN oba.YEAR_BUILT<='2019' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2019, SUM(CASE WHEN oba.YEAR_BUILT<='2020' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2020, SUM(CASE WHEN oba.YEAR_BUILT<='2021' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2021, SUM(CASE WHEN oba.YEAR_BUILT<='2022' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2022, SUM(CASE WHEN oba.YEAR_BUILT<='2023' OR oba.YEAR_BUILT IS NULL THEN 1 ELSE 0 END) AS y2023 FROM open_bridges oba GROUP BY oba.structure_type ), gikl_stats AS ( SELECT gika.Structure_type, SUM(CASE WHEN EXTRACT(YEAR FROM gika.status_granted_date) >=2016 THEN 1 ELSE 0 END) AS gik2016 FROM gikl_all_strucs gika GROUP BY gika.structure_type ) SELECT os.Structure_type, os.y2016, COALESCE(gs.gik2016, 0) AS gik2016, os.y2017, os.y2018, os.y2019, os.y2020, os.y2021, os.y2022, os.y2023 FROM open_bridges_stats os LEFT JOIN gikl_stats gs ON os.Structure_type = gs.Structure_type ORDER BY os.Structure_type DESC;
修正要点
- 先分别对两个CTE按
structure_type完成统计,得到各自的汇总结果 - 仅通过
structure_type关联两个汇总表,避免原始数据无匹配的问题 - 使用
COALESCE处理NULL值,确保无匹配时显示0 - 修正字段名错误,将
current_status_granted_date改回status_granted_date
内容的提问来源于stack exchange,提问作者ar ia
相关产品推荐
相关产品推荐

