根据一组左联接记录的条件设置标志的查询

Query that sets a flag based on a condition for a group of left joined records

提问人:Krikey 提问时间:8/23/2023 最后编辑:Krikey 更新时间:8/28/2023 访问量:68

问:

我有 2 个表,“制造商”和“产品”。制造商可以有多个产品,一个产品有一个“数量”、“价格”和“成本”字段。

制造商表

manufacturer_id 名字
1 美国广播公司
2 流星
3 XYZ公司
4 Airfix的

产品表

product_id manufacturer_id 价格 成本 数量
100 1 123.32 32.23 32
101 2 123.32 32.23 23
102 3 123.32 32.23 16
103 2 123.32 32.23 8
104 1 123.32 12.45 5
105 3 123.32 0.00 3
106 3 123.32 32.23 99
107 4 123.32 32.23 88

我已经离开了将它们连接在一起,并且可以通过乘以“数量”在“价格”和“成本”字段上获得 SUM,但是如果未设置来自特定制造商的任何 product.cost 字段,我想将“cost_complete”标志设置为 false,从而允许我识别任何拥有尚未设置“成本”的产品的制造商。

这是我目前所拥有的,但我认为我的“cost_complete”标志会被每个产品覆盖。

SELECT m.name, p.quantity, p.price, p.cost, 
SUM(p.quantity) AS total_quantity,
SUM(p.price*p.quantity) AS total_price,
SUM(p.cost*p.quantity) AS total_cost, IF(p.cost>0, 'true','false') AS cost_complete
FROM manufacturer m LEFT JOIN product p ON m.manufacturer_id = p.manufacturer_id GROUP BY m.manufacturer_id ORDER by m.name

修改以解释我所期望的:

名字 数量 total_price total_cost cost_complete
美国广播公司 56 £345.23 £123.32
流星 12 £1345.23 £23.32
XYZ公司 123 £345.23 £65.12
Airfix的 66 £445.23 £12.12

...其中,当并非所有成本字段的值都大于 0 时,cost_complete 列设置为 false。

mysql if-statement 左联接 ifnull

评论

0赞 Ergest Basha 8/23/2023
请参阅 #5 和 #3 提示,以提出一个好的结构化查询语言 (SQL) 问题并更新 qestion
0赞 Krikey 8/25/2023
编辑以解释表格结构以及我希望输出的样子。
0赞 user1191247 9/5/2023
当前查询应触发 1055 错误。如果没有,则您禁用了ONLY_FULL GROUP BY,这是您不应该禁用的。请阅读 GROUP BY 的 MySQL 处理only_full_group_by 模式有什么好处?。检查此 db<>fiddle

答:

0赞 nacho 8/23/2023 #1

如果 p.cost 为 null(或低于代码中的 0),则可以执行条件求和。然后,您将拥有没有 p.cost 的产品数量(如果为 0,则所有产品都有成本)

SELECT m.name, p.quantity, p.price, p.cost, SUM(p.quantity) AS total_quantity, 
    SUM(p.price*p.quantity) AS total_price, SUM(p.cost*p.quantity) AS total_cost, 
    sum(case when p.cost>0 then 1 else 0 end) 
FROM manufacturer m 
LEFT JOIN product p ON m.manufacturer_id = p.manufacturer_id 
GROUP BY m.manufacturer_id 
ORDER by m.name

P.D.(英语:P.D.)要回答您的评论,您可以通过以下方式进行操作:

SELECT m.name, p.quantity, p.price, p.cost, SUM(p.quantity) AS total_quantity, 
    SUM(p.price*p.quantity) AS total_price, SUM(p.cost*p.quantity) AS total_cost, 
    min(case when p.cost>0 then true else false end) 
FROM manufacturer m 
LEFT JOIN product p ON m.manufacturer_id = p.manufacturer_id 
GROUP BY m.manufacturer_id 
ORDER by m.name

评论

0赞 Krikey 8/25/2023
我修改了我原来的问题,以提供一个示例,说明 Id 喜欢输出的样子。如果任何产品“成本”字段为 0 或 NULL,则cost_complete列将为 false。
0赞 nacho 8/25/2023
我已经修改了我的答案以满足您的评论要求
0赞 Krikey 8/25/2023
这似乎为min(p.cost为null时为false,否则为true end)部分返回一个“1”,无论每个p.cost是0,NULL还是具有正值
0赞 UncleCarl 8/29/2023
为什么使用单选项 CASE 而不是 IF?
0赞 Christian 8/23/2023 #2

若要查询至少具有一种未设置成本的产品的制造商列表,应执行此查询。

SELECT
    m.name,
    SUM(p.quantity) AS total_quantity,
    SUM(p.price * p.quantity) AS total_price,
    SUM(p.cost * p.quantity) AS total_cost,
    MIN(IFNULL(p.cost, 0)) AS min_cost            # 👈 see no. 2.4
FROM manufacturer m
    LEFT JOIN product p ON m.manufacturer_id = p.manufacturer_id
GROUP BY m.manufacturer_id
HAVING min_cost = 0                               # 👈 see no. 3
ORDER BY m.name;

我想想象一下这个查询的作用如下:

  1. 对于每个制造商,获取其制造的产品列表。
  2. 对于步骤 1 中的每个产品列表,请浏览每个产品并执行以下操作:
    1. 聚合数量 (as ),total_quantity
    2. 聚合价格(如),total_price
    3. 汇总总成本 (as ),以及total_cost
    4. 请注意筛选的所有产品中的最低成本 (as )。min_cost
  3. 仅在最小产品成本 () 为零的制造商中筛选。min_cost
  4. 输出制造商信息,以及在步骤 2 中收集的汇总信息。
  5. 按制造商名称对步骤 4 进行排序。

请注意我是如何从语句中删除 、 和 的。这是因为我们使用该语句来汇总有关制造商下的产品列表的摘要;没有选择单一的产品。简而言之,将它们包括在内是没有意义的,因为同一制造商下可能有多个产品没有设置。p.quantityp.pricep.costSELECTSELECTcost

此外,如评论中所述,我使用的是子句中命名的别名。这是标准 SQL 的 MySQL 扩展,默认情况下语法有效,除非设置为 。min_costHAVINGsql_modeONLY_FULL_GROUP_BY