提问人:Krikey 提问时间:8/23/2023 最后编辑:Krikey 更新时间:8/28/2023 访问量:68
根据一组左联接记录的条件设置标志的查询
Query that sets a flag based on a condition for a group of left joined records
问:
我有 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。
答:
如果 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
评论
若要查询至少具有一种未设置成本的产品的制造商列表,应执行此查询。
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 中的每个产品列表,请浏览每个产品并执行以下操作:
- 聚合数量 (as ),
total_quantity
- 聚合价格(如),
total_price
- 汇总总成本 (as ),以及
total_cost
- 请注意筛选的所有产品中的最低成本 (as )。
min_cost
- 聚合数量 (as ),
- 仅在最小产品成本 () 为零的制造商中筛选。
min_cost
- 输出制造商信息,以及在步骤 2 中收集的汇总信息。
- 按制造商名称对步骤 4 进行排序。
请注意我是如何从语句中删除 、 和 的。这是因为我们使用该语句来汇总有关制造商下的产品列表的摘要;没有选择单一的产品。简而言之,将它们包括在内是没有意义的,因为同一制造商下可能有多个产品没有设置。p.quantity
p.price
p.cost
SELECT
SELECT
cost
此外,如评论中所述,我使用的是子句中命名的别名。这是标准 SQL 的 MySQL 扩展,默认情况下语法有效,除非设置为 。min_cost
HAVING
sql_mode
ONLY_FULL_GROUP_BY
评论
了ONLY_FULL GROUP BY
,这是您不应该禁用的。请阅读 GROUP BY 的 MySQL 处理 和 only_full_group_by 模式有什么好处?。检查此 db<>fiddle。