Oracle中外连接按日期分别关联:补全位置日期组合统计结果
生成日期与位置全组合的统计结果(缺失值补0)
我明白你的问题了——你需要的是指定日期范围内所有日期和所有位置的笛卡尔积组合,哪怕某个组合在表A里没有数据,也要显示出来并把sum设为0。之前用右连接表B没成功,是因为你缺少了「生成全量日期列表」这一步,原来的查询只返回了有数据的日期,没法和所有位置组合出完整的结果。
下面是具体的解决方案:
核心思路
- 生成需要统计的所有日期列表:先把你要的13-June-11和14-June-11这两个日期单独列出来(如果日期范围更大,可以用动态生成的方式)。
- 生成日期+位置的全组合:用笛卡尔积(
CROSS JOIN)把日期列表和表B的所有位置组合起来,得到所有可能的(date, location)对。 - 左连接统计数据并补0:把全组合的结果左连接到你原来的统计查询上,用
NVL()函数把没有数据的sum值替换成0。
完整SQL示例
SELECT TRUNC(d.stat_date) AS trun_date, b.location, NVL(a.sum_credit, 0) AS sum FROM ( -- 步骤1:生成需要统计的所有目标日期 SELECT TO_DATE('13/JUN/2011', 'dd/mon/yyyy') AS stat_date FROM dual UNION ALL SELECT TO_DATE('14/JUN/2011', 'dd/mon/yyyy') AS stat_date FROM dual ) d CROSS JOIN table_b b -- 步骤2:笛卡尔积得到所有日期+位置的组合 LEFT JOIN ( -- 步骤3:原来的统计逻辑,只计算有数据的组合的sum SELECT TRUNC(date_time) AS stat_date, location, SUM(credit) AS sum_credit FROM table_a WHERE date_time >= TO_DATE('13/JUN/2011', 'dd/mon/yyyy') AND date_time <= TO_DATE('15/JUN/2011', 'dd/mon/yyyy') GROUP BY TRUNC(date_time), location ) a ON d.stat_date = a.stat_date AND b.location = a.location ORDER BY d.stat_date DESC, b.location; -- 按日期倒序、位置排序,和你期望的结果一致
为什么之前的右连接不行?
你之前尝试的右连接表B,只能把有数据的日期对应的缺失位置补全,但没法生成「没有数据的日期」对应的所有位置。比如如果表A里14号没有位置A的数据,右连接只能补14号的A,但如果某个日期完全没有数据(比如假设15号没有任何记录),右连接根本不会显示15号的任何位置。而先生成全量日期列表再做笛卡尔积,就能确保所有日期和位置的组合都被包含。
另外,你原来的查询里用了MIN(LOCATION)是多余的——因为你已经按LOCATION分组了,直接选LOCATION就行。
内容的提问来源于stack exchange,提问作者user5078583
相关产品推荐
相关产品推荐

