如何在 SELECT 查询中使用聚合函数和 CASE WHEN THEN
Posted
技术标签:
【中文标题】如何在 SELECT 查询中使用聚合函数和 CASE WHEN THEN【英文标题】:How do I use aggregate function and CASE WHEN THEN in SELECT query 【发布时间】:2021-09-01 05:45:25 【问题描述】:我有 3 张桌子:
-
sales_fact(fact_date、prod_id、fact_sum)
sales_pred(pred_date、prod_id、pred_sum)
产品(prod_id、名称、价格)
我需要制作一份报告,其中包含以下列: 年 月 产品名称 事实销售 预计销售 偏差
如果实际销售为空,则偏差 = 预测销售; 如果 Predicted sales 为空,则偏差 = -Fact sales
我在最后一个条件下遇到了困难。帮助我理解我的错误
我的代码:
SELECT year(fact_date) AS Year,
month(fact_date) AS Month,
product.name AS Name,
ROUND(SUM(fact_sum), 2) AS Fact,
ROUND(SUM(pred_sum), 2) AS Prediction,
(CASE
WHEN SUM(pred_sum) IS NULL AND SUM(fact_sum) IS NOT NULL
THEN ROUND(-(SUM(fact_sum)), 2)
WHEN SUM(fact_sum) IS NULL AND SUM(pred_sum) IS NOT NULL
THEN ROUND(SUM(pred_sum)), 2)
WHEN SUM(pred_sum) IS NOT NULL AND SUM(fact_sum) IS NOT NULL
THEN ROUND(SUM(pred_sum) - (SUM(fact_sum)), 2)
ELSE 0 END AS Deviation
FROM sales_fact
LEFT JOIN product ON sales_fact.prod_id = product.prod_id
LEFT JOIN sales_pred ON sales_pred.prod_id = product.prod_id AND sales_pred.pred_date = sales_fact.fact_date
GROUP BY product.name, month(fact_date), year(fact_date);
创建表格的代码:
create table sales_fact (fact_date date, prod_id varchar(30), fact_sum float);
insert into sales_fact (fact_date, prod_id, fact_sum) values ('2016-03-25', '2271145', 93.31);
insert into sales_fact (fact_date, prod_id, fact_sum) values ('2016-04-25', '2271146', 13.31);
insert into sales_fact (fact_date, prod_id, fact_sum) values ('2016-05-25', '2271147', 83.31);
insert into sales_fact (fact_date, prod_id, fact_sum) values ('2016-03-25', '2271145', 43.31);
insert into sales_fact (fact_date, prod_id, fact_sum) values ('2016-07-25', '2271148', 73.31);
insert into sales_fact (fact_date, prod_id, fact_sum) values ('2016-07-25', '2271147', 13.31);
insert into sales_fact (fact_date, prod_id, fact_sum) values ('2016-08-25', '2271149', 43.31);
insert into sales_fact (fact_date, prod_id, fact_sum) values ('2016-09-25', '2271148', 33.31);
create table sales_pred (pred_date date, prod_id varchar(30), pred_sum float);
insert into sales_pred (pred_date, prod_id, pred_sum) values ('2016-03-25', '2271145', 100);
insert into sales_pred (pred_date, prod_id, pred_sum) values ('2016-04-25', '2271146', 93.31);
insert into sales_pred (pred_date, prod_id, pred_sum) values ('2016-05-25', '2271147', 103.31);
insert into sales_pred (pred_date, prod_id, pred_sum) values ('2016-07-25', '2271148', 73.31);
create table product (prod_id varchar(30), name varchar(30), price float);
insert into product (prod_id, name, price) values ('2271145', 'phone', 3);
insert into product (prod_id, name, price) values ('2271147', 'laptop', 4);
insert into product (prod_id, name, price) values ('2271148', 'PC', 5);
insert into product (prod_id, name, price) values ('2271146', 'mouse', 2);
insert into product (prod_id, name, price) values ('2271149', 'airpods', 7);
【问题讨论】:
我有 3 个表您必须为这些表提供完整的 CREATE TABLE - 这对问题至关重要。 请提供少量样本数据。 看起来您将 NULL 视为零,这通常是不正确的。如果您有应该为零的空值,则最好将它们固定为零。如果它们不应该为零,那么如果计算中存在空值,则 Deviation 可能应该返回 NULL。 附言。ROUND(SUM(pred_sum) - SUM(fact_sum), 2)
ROUND(SUM(pred_sum), 2) - ROUND(SUM(fact_sum), 2)
.
只要使用COALESCE
,就不需要CASE
,例如COALESCE(SUM(pred_sum),0) - COALESCE(SUM(fact_sum),0)
【参考方案1】:
根据您的条件偏差可能为负,因此只需使用减法并使用 colaesce() 将 NULL 值转换为 0(零)。
-- mysql
SELECT YEAR(sf.fact_date) year
, MONTH(sf.fact_date) month
, p.name
, COALESCE(ROUND(SUM(sf.fact_sum), 2), 0) fact
, COALESCE(ROUND(SUM(slp.pred_sum), 2), 0) Prediction
, ROUND(COALESCE(SUM(slp.pred_sum), 0) - COALESCE(SUM(sf.fact_sum), 0), 2) deviation
FROM sales_fact sf
LEFT JOIN product p
ON sf.prod_id = p.prod_id
LEFT JOIN sales_pred slp
ON slp.prod_id = p.prod_id
AND slp.pred_date = sf.fact_date
GROUP BY YEAR(sf.fact_date), MONTH(sf.fact_date), p.name;
请查看网址https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=a9e9f21dd36400d8830a4734aa7ffb29
【讨论】:
如果偏差必须为正,那么ABS()
更简单。正如您所指出的,OP 对此并不明确/不合逻辑。根据 OP 代码,如果两个总和都有值,则可能出现负数。如果预测为空,那么显示正数就没有逻辑意义。总是将偏差作为正数会产生一个毫无意义的数字,因为你不知道它是盈余还是赤字。
顺便说一句,如果您写的答案基本上详细说明了别人的 cmets,承认这一事实通常被认为是礼貌的。
感谢@JonathanWillcock 的观察。是的 ABS() 更好。如果提问者提供预期的输出会更好。需要提问者的回答。以上是关于如何在 SELECT 查询中使用聚合函数和 CASE WHEN THEN的主要内容,如果未能解决你的问题,请参考以下文章