MySQL技术问询:按日期分组展示部门促销销售及无销售日期
没问题,我来帮你搞定这个查询问题!
首先得理清你遇到的核心问题:
- 当你把
dp.product_id = pr.product_id加到WHERE子句时,左连接的特性直接失效了——这个条件会过滤掉所有pr.product_id为NULL的行,也就是没有销售的记录,自然就丢失了无销售的日期。 - 另外你原来的查询会把每个促销活动(a/b/c)都单独显示一行,但你期望无销售的日期只保留一行NULL记录,而不是三行重复的空值。
解决方案:
我们需要先锁定目标campaign下的所有日期,再关联有实际销售的记录,最后对无销售的日期单独补充一行空值。这里用CTE(公共表表达式)来拆分逻辑,更清晰易懂:
WITH campaign_dates AS ( -- 第一步:获取campaign_id=1对应的所有唯一日期 SELECT DISTINCT DATE(created) AS created_date FROM promotion_result WHERE campaign_id = 1 ), valid_sales AS ( -- 第二步:筛选出有实际销售的记录(排除product_id为NULL的行) SELECT DATE(pr.created) AS created_date, pr.campaign_id, pr.promotion, pr.product_id FROM department dept JOIN department_campaign dc ON dc.department_id = dept.id JOIN promotion_result pr ON dc.campaign_id = pr.campaign_id WHERE dept.id = 2 AND pr.campaign_id = 1 AND pr.product_id IS NOT NULL ) -- 第三步:合并有销售的记录和无销售日期的空值行 SELECT created_date AS created, campaign_id AS campaign, promotion, product_id AS product FROM valid_sales UNION ALL SELECT created_date AS created, 1 AS campaign, NULL AS promotion, NULL AS product FROM campaign_dates cd WHERE NOT EXISTS ( -- 只补充那些没有销售记录的日期 SELECT 1 FROM valid_sales vs WHERE vs.created_date = cd.created_date ) ORDER BY created ASC, promotion ASC;
逻辑说明:
campaign_dates:先把目标campaign下的所有日期提取出来,确保不会遗漏任何日期节点。valid_sales:只保留有实际销售的记录,避免左连接带来的多余空行。- 最后合并查询:用
UNION ALL把有销售的记录,和没有销售日期的单行空值记录合并,完美匹配你想要的结果。
为什么原来的查询不生效?
- 你添加的
dp.product_id = pr.product_id条件,把左连接变成了内连接——因为pr.product_id为NULL时,不可能和dp.product_id匹配,直接过滤掉了无销售的行。 - 原来的
GROUP BY会按每个促销活动分组,导致无销售日期出现三行空值,而我们需要的是将这些空值合并为一行。
内容的提问来源于stack exchange,提问作者bm82
相关产品推荐
相关产品推荐

