如何让SQL JOIN统计NULL值,显示所有产品类型的销量
问题分析
你的问题出在WHERE子句的过滤条件上:YEAR(S.SellDate) = 2022会把RIGHT JOIN后没有销售记录的行(此时S.SellDate为NULL)直接排除,因为YEAR(NULL)的结果是NULL,无法满足=2022的条件,导致未售出的产品类型行消失。
解决方案
方案1:将年份条件移至JOIN的ON子句(简单版)
把过滤2022年销售记录的条件从WHERE移到JOIN的ON中,这样只会匹配Items表中2022年的记录,不会影响Types表的所有行。同时,统计销量时要使用COUNT(S.TypeID)(而非COUNT(T.ID)),因为没有销售记录时S.TypeID是NULL,COUNT会忽略NULL值,得到0:
SELECT YEAR(S.SellDate) AS Year, MONTH(S.SellDate) AS Month, T.ID as ProdType, T.[Description] as ProdDescription, COUNT(S.TypeID) AS Sold FROM Types T LEFT JOIN Items S ON S.TypeID = T.ID AND YEAR(S.SellDate) = 2022 -- 年份条件移到ON中 GROUP BY YEAR(S.SellDate), MONTH(S.SellDate), T.ID, T.[Description] ORDER BY 1, 2, 3 ASC
如果希望未销售的行也显示2022年(而非NULL),可以用COALESCE函数固定年份:
SELECT COALESCE(YEAR(S.SellDate), 2022) AS Year, MONTH(S.SellDate) AS Month, T.ID as ProdType, T.[Description] as ProdDescription, COUNT(S.TypeID) AS Sold FROM Types T LEFT JOIN Items S ON S.TypeID = T.ID AND YEAR(S.SellDate) = 2022 GROUP BY COALESCE(YEAR(S.SellDate), 2022), MONTH(S.SellDate), T.ID, T.[Description] ORDER BY 1, 2, 3 ASC
方案2:生成完整的月份+产品类型组合(完整维度版)
如果需要每个产品类型在2022年的每个月份都显示一行(即使该月无销售),可以先生成2022年的所有月份,再和Types表做笛卡尔积,最后LEFT JOIN销售数据:
SELECT 2022 AS Year, M.Month, T.ID as ProdType, T.[Description] as ProdDescription, COUNT(S.TypeID) AS Sold FROM Types T -- 生成2022年1-12月的维度表 CROSS JOIN ( SELECT 1 AS Month UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12 ) M LEFT JOIN Items S ON S.TypeID = T.ID AND YEAR(S.SellDate) = 2022 AND MONTH(S.SellDate) = M.Month GROUP BY 2022, M.Month, T.ID, T.[Description] ORDER BY 1, 2, 3 ASC
这个方案能确保每个产品类型在2022年的12个月份都有记录,无销售时Sold显示0,Year和Month也会正确显示对应值。
内容的提问来源于stack exchange,提问作者jcf
相关产品推荐
相关产品推荐

