使用WITH AS编写SQL月度销售对比查询结果行数异常求助
解决WITH AS查询返回笛卡尔积的问题
你遇到的这个问题很常见——当前查询里用了SELECT * FROM TABLE_CURRENT, TABLE_LAST这种隐式交叉连接,它会把两个CTE的所有行做全组合匹配,所以如果每个CTE各有3行,结果自然就是3×3=9行,也就是你看到的“平方数行数”。
要得到按月度对比的3行数据,核心是让今年的每个月份和去年对应的月份做一对一关联,而不是全组合。这里给你两种修改思路:
方法1:提取月份字段做显式JOIN
修改两个CTE,额外单独提取月份数字,然后用INNER JOIN关联相同的月份,确保每行都是同月份的新老数据对比:
DECLARE @MAX_DATE AS INT SET @MAX_DATE = (SELECT DATEPART(MONTH,FECHA) FROM ALBVENTACAB WHERE NUMALBARAN IN (SELECT DISTINCT MAX(NUMALBARAN) FROM ALBVENTACAB)); ;WITH TABLE_LAST AS ( SELECT DATEPART(MONTH,FECHA) AS MONTH_NUM -- 单独提取月份数字用于关联 ,CONCAT(DATEPART(MONTH,FECHA),'-',DATEPART(YEAR,FECHA)) as LAST_YEAR_MONTH ,SUM(TOTALNETO) AS LAST_YEAR_VALUE FROM ALBVENTACAB WHERE DATEPART(YEAR,CURRENT_TIMESTAMP) -1 = DATEPART(YEAR,FECHA) AND NUMSERIE LIKE 'A%' AND DATEPART(MONTH,FECHA) <= @MAX_DATE GROUP BY DATEPART(MONTH,FECHA), CONCAT(DATEPART(MONTH,FECHA),'-',DATEPART(YEAR,FECHA)) ) ,TABLE_CURRENT AS( SELECT DATEPART(MONTH,FECHA) AS MONTH_NUM -- 同样提取月份数字 ,CONCAT(DATEPART(MONTH,FECHA),'-',DATEPART(YEAR,FECHA)) as CURR_YEAR_MONTH ,SUM(TOTALNETO) AS CURR_YEAR_VALUE FROM ALBVENTACAB WHERE DATEPART(YEAR,CURRENT_TIMESTAMP) = DATEPART(YEAR,FECHA) AND NUMSERIE LIKE 'A%' AND DATEPART(MONTH,FECHA) <= @MAX_DATE -- 加上@MAX_DATE和去年保持一致的月份范围 GROUP BY DATEPART(MONTH,FECHA), CONCAT(DATEPART(MONTH,FECHA),'-',DATEPART(YEAR,FECHA)) ) SELECT TC.CURR_YEAR_MONTH, TC.CURR_YEAR_VALUE, TL.LAST_YEAR_MONTH, TL.LAST_YEAR_VALUE FROM TABLE_CURRENT TC INNER JOIN TABLE_LAST TL ON TC.MONTH_NUM = TL.MONTH_NUM -- 关联相同月份
方法2:直接拆分日期字符串关联
如果不想修改CTE结构,也可以通过拆分LAST_YEAR_MONTH和CURR_YEAR_MONTH的月份部分来做关联:
-- 前面的CTE部分保持不变 SELECT TC.CURR_YEAR_MONTH, TC.CURR_YEAR_VALUE, TL.LAST_YEAR_MONTH, TL.LAST_YEAR_VALUE FROM TABLE_CURRENT TC INNER JOIN TABLE_LAST TL ON LEFT(TC.CURR_YEAR_MONTH, CHARINDEX('-', TC.CURR_YEAR_MONTH)-1) = LEFT(TL.LAST_YEAR_MONTH, CHARINDEX('-', TL.LAST_YEAR_MONTH)-1)
另外提个小建议:你的TABLE_CURRENT里的条件DATEPART(YEAR,CURRENT_TIMESTAMP) <= DATEPART(YEAR,FECHA)可能会包含未来年份的数据(如果表中有),建议改成DATEPART(YEAR,CURRENT_TIMESTAMP) = DATEPART(YEAR,FECHA),同时加上DATEPART(MONTH,FECHA) <= @MAX_DATE,这样今年和去年的月份范围保持一致,避免出现去年没有的月份导致关联不上的情况。
内容的提问来源于stack exchange,提问作者Fawad Jalal
相关产品推荐
相关产品推荐

