SQL Server 如何按商品类型合并销售数据并补齐零销量?
数据小陈
结论
可以先为每位买家和每种商品类型生成组合,再用 LEFT JOIN 关联销售数量,最后通过条件聚合将商品类型展开为列。这样即使某种类型没有销售记录,也会保留该类型,并将数量显示为 0。
题目中的 INNER JOIN 会丢掉没有匹配销售记录的商品类型。示例查询中,SELL_DETAILS 使用了 B.PID,但表格里的列名是 ID。下面假设 Sell_Detail.ID 是买家 ID,Sell_Detail.SL 对应 BillingDetails.SL。如果实际列名是 PID,请将查询中的 sd.ID 改为 sd.PID。如果表名或列名与数据库中的实际名称不同,也需要相应调整。
查询示例
WITH SalesByType AS (
SELECT
sd.ID AS BuyerID,
sd.TYPEID,
SUM(COALESCE(bd.QTY, 0)) AS QTY
FROM Sell_Detail AS sd
LEFT JOIN BillingDetails AS bd
ON bd.[Sl No] = sd.[Sl No]
GROUP BY
sd.ID,
sd.TYPEID
)
SELECT
b.ID,
b.NAME,
MAX(CASE WHEN p.TYPEID = 1 THEN p.TNAME END) AS TNAME1,
COALESCE(MAX(CASE WHEN p.TYPEID = 1 THEN s.QTY END), 0) AS QTY1,
MAX(CASE WHEN p.TYPEID = 2 THEN p.TNAME END) AS TNAME2,
COALESCE(MAX(CASE WHEN p.TYPEID = 2 THEN s.QTY END), 0) AS QTY2,
MAX(CASE WHEN p.TYPEID = 3 THEN p.TNAME END) AS TNAME3,
COALESCE(MAX(CASE WHEN p.TYPEID = 3 THEN s.QTY END), 0) AS QTY3
FROM Buyer AS b
CROSS JOIN Product AS p
LEFT JOIN SalesByType AS s
ON s.BuyerID = b.ID
AND s.TYPEID = p.TYPEID
GROUP BY
b.ID,
b.NAME
ORDER BY
b.ID;
如果账单明细表中的列名不带空格,例如是 SL,可以将 bd.[Sl No] 改为 bd.SL。销售明细中的列名也是如此:如果实际列名是 SL,请将 sd.[Sl No] 改为 sd.SL。
为什么这样能补齐并合并结果
SalesByType 先按买家和商品类型汇总数量。接着,Buyer CROSS JOIN Product 为每位买家和每种商品类型生成一行,再通过 LEFT JOIN 关联汇总数量。没有销售记录时,数量为 NULL,可用 COALESCE(..., 0) 将其转为 0。
MAX(CASE WHEN ... THEN ... END) 会将类型为 1、2、3 的记录分别放入固定列。这里的 TYPEID 和输出列根据题目示例设定。如果商品类型会变化,可以用动态 SQL 生成列,也可以让结果按每位买家多行的形式保留。
同一买家和商品类型有多条销售明细时,查询会先将这些明细的 QTY 相加。如果业务要求只取单条明细,或采用其他统计方式,需要相应调整 SalesByType 中的聚合逻辑。
备注:内容仅供参考。
