我有两个表(仅列出对该问题重要的字段):
t_groups
INT groupId主
VARCHAR(255)grname
货物
INT goodId主要
INT groupId
INT价格
VARCHAR(255)名称
现在,我需要一个查询,该查询选择组名和每个组中最便宜商品的名称。尝试这样做:
SELECT gr.groupId, grname, g.name
FROM t_groups AS gr
LEFT JOIN (SELECT * FROM t_goods ORDER BY PRICE ASC LIMIT 1) AS g
ON g.groupId = gr.groupId
但它不起作用-在g.name字段中返回NULL。这很容易解释:
JOIN语句中的SELECT首先选择最便宜的商品,然后尝试通过groupId“对其进行过滤”。显然,它仅对最便宜的商品所属的类别有效。
我该如何解决任务?
最佳答案
为什么查询不起作用
SELECT gr.groupId, grname, g.name
FROM t_groups AS gr
LEFT JOIN (SELECT * FROM t_goods ORDER BY PRICE ASC LIMIT 1) AS g
ON g.groupId = gr.groupId
内部查询选择数据库中绝对便宜的商品(与组无关)。因此,当您将组
LEFT JOIN
归入此结果集时,只有实际包括全球最便宜商品的组才具有匹配的行(该组应正确填充g.name
列)。但是,由于LEFT JOIN
的工作方式,所有其他组将获得NULL
作为g
中所有列的值。正确的解决方案
首先,您需要在每个组中选择最便宜的价格。这很容易:
SELECT groupId, MIN(price) AS minPrice FROM t_goods GROUP BY (groupId)
但是,如果没有关联的
goodId
,则最便宜的价格将无用。问题是写这样的东西是没有意义的:/* does not make sense, although MySql has historically allowed it */
SELECT goodId, groupId, MIN(price) AS minPrice FROM t_goods GROUP BY (groupId)
原因是,除非将其包装在聚合函数(例如
goodId
)中,否则无法选择未分组的列(即MIN
):我们不知道要从共享的列中选择哪个goodId
相同的groupId
。获取每组中最便宜商品的
goodId
的正确,便携式方法是SELECT goodId, temp.groupId, temp.minPrice
FROM (SELECT groupId, MIN(price) AS minPrice FROM t_goods GROUP BY groupId) temp
JOIN t_goods ON temp.groupId = t_goods.groupId AND temp.minPrice = t_goods.price)
上面的查询首先找出每组中最便宜的价格,然后再次连接到商品表以查找该组中具有该价格的商品的
goodId
。重要提示:如果一组商品中最便宜的商品价格相等,则该查询将返回所有商品。如果每个组只想要一个结果,则必须指定决胜局,例如:
SELECT MIN(goodId), temp.groupId, MIN(temp.minPrice)
FROM (SELECT groupId, MIN(price) AS minPrice FROM t_goods GROUP BY groupId) temp
JOIN t_goods ON temp.groupId = t_goods.groupId AND temp.minPrice = t_goods.price)
GROUP BY temp.groupId
有了这个查询,您就可以找到每个组中最便宜的商品的名称和价格(最低的
goodId
将用作决胜局):SELECT groupId, grname, gd.name, t3.minPrice
FROM t_groups AS gr
LEFT JOIN (SELECT MIN(goodId) AS goodId, t1.groupId, MIN(t1.minPrice) AS minPrice
FROM (SELECT groupId, MIN(price) AS minPrice FROM t_goods GROUP BY groupId) t1
JOIN t_goods ON t1.groupId = t_goods.groupId AND t1.minPrice = t_goods.price
) t2
) t3 ON gr.groupId = t3.groupId
LEFT JOIN t_goods gd ON t3.goodId = gd.goodId
此最终查询在其“外部”级别执行两个联接:
使用“每个组的
goodId
和最便宜的价格”表加入组以获取goodId
和最便宜的价格然后通过此
goodId
与商品表结合以获取商品名称即使以最低的价格捆绑多种商品,每组也只会生产一种商品。
关于mysql - 在JOIN中选择最小值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10121979/