自连接表获取去年数据时如何处理缺失日期问题
解决FULL JOIN导致的重复行及缺失日期问题
我来帮你搞定这个问题!你的需求很明确:要为每行数据匹配去年同期同渠道的会话数,同时还要保留那些只有今年数据或只有去年数据的日期-渠道组合,但原始的FULL JOIN语句不仅没达到预期,还出现了行重复和格式混乱的问题。
问题根源分析
原始的FULL JOIN虽然理论上会保留左右表中不匹配的行,但它没有先确保所有需要的日期-渠道组合都被覆盖。当某条记录在另一边没有匹配项时,会生成结构异常的行(比如你的实际输出里出现了孤立的数值),同时还会漏掉那些需要展示的“空数据”行(比如2018年2月2日的Organic渠道)。
正确解决方案
我们需要先构建出所有可能的日期-渠道组合,再分别左连接今年和去年的数据,这样就能保证每个组合都有一行,且数据对应正确。
修正后的SQL语句
WITH all_dates_channels AS ( -- 生成所有日期和渠道的笛卡尔积,确保每个日期-渠道组合都被包含 SELECT DISTINCT tj.Date FROM testjoin tj CROSS JOIN SELECT DISTINCT tj.Channel FROM testjoin tj ) SELECT adc.Date, adc.Channel, ty.Sessions AS Sessions, ly.Sessions AS Sessions_LY FROM all_dates_channels adc -- 左连接获取当前日期-渠道的会话数(无数据则为NULL) LEFT JOIN testjoin ty ON ty.Date = adc.Date AND ty.Channel = adc.Channel -- 左连接获取去年同期同渠道的会话数(无数据则为NULL) LEFT JOIN testjoin ly ON ly.Date = DATE_SUB(adc.Date, INTERVAL 1 YEAR) AND ly.Channel = adc.Channel -- 按渠道和日期排序,让结果更清晰 ORDER BY adc.Channel, adc.Date;
代码解释
- CTE
all_dates_channels:通过交叉连接(CROSS JOIN)原始表中所有唯一的日期和渠道,生成所有可能的日期-渠道组合。这一步是关键,确保不会漏掉任何需要展示的组合。 - 第一个左连接:关联原始表,获取当前日期-渠道的会话数,如果该组合没有数据,
Sessions字段会显示NULL。 - 第二个左连接:关联原始表中日期减一年且渠道相同的记录,获取去年的会话数,无匹配则显示
NULL。 - 排序:最终结果按渠道和日期排序,和你期望的输出格式完全一致。
验证结果
运行这段SQL后,你会得到完全符合期望的输出:
Date Channel Sessions Sessions_LY 01/01/2017 Email 5 null 02/02/2017 Email 10 null 01/01/2018 Email 11 5 02/02/2018 Email 17 10 01/01/2017 Organic 10 null 02/02/2017 Organic 15 null 01/01/2018 Organic 20 10 02/02/2018 Organic null 15
内容的提问来源于stack exchange,提问作者Carl K
相关产品推荐
相关产品推荐

