MySQL Left join 无法在单个查询中删除重复项
Posted
技术标签:
【中文标题】MySQL Left join 无法在单个查询中删除重复项【英文标题】:MySQL Left join cannot remove duplicates in a single query 【发布时间】:2020-05-10 20:48:13 【问题描述】:我有 2 张桌子:
产品:
- id
- name
产品图片:
- id
- image
- product_id
我正在执行以下查询:
SELECT p.*, i.image
FROM products p
LEFT JOIN product_images i
ON p.id = i.product_id`
ORDER BY created_at DESC
但是,如果产品有几张图片,则此产品行是重复的。如何删除这些重复项,仅显示一对 p.id = i.product_id
中的第一个匹配项
【问题讨论】:
GROUP BY
应该可以帮到你。
请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入作为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出尽可能少的代码,即您显示的代码可以通过您显示的代码扩展为不正常的代码。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)和输入为格式化为表的代码的 SQL。 How to Ask 暂停总体目标的工作,将代码砍到第一个表达式,没有给出你期望的内容,说出你期望的内容和原因。
【参考方案1】:
对于这个数据集,简单的聚合应该可以做到:
SELECT p.*, min(i.image)
FROM products p
LEFT JOIN product_images i ON p.id = i.product_id
GROUP BY <enumerate all columns from products here>
ORDER BY created_at DESC
LIMIT $limit
如果您想要来自product_images
的更多列,那么您也可以使用相关子查询进行过滤;假设product_images
有主键id
,看起来像:
SELECT p.*, i.image
FROM products p
LEFT JOIN product_images i
ON i.id = (SELECT MIN(i1.id) FROM product_images i1 WHERE i1.product_id = p.id)
ORDER BY created_at DESC
LIMIT $limit
【讨论】:
谢谢,在您的第一个示例中,您写道:GROUP BY <enumerate all columns from products>
,如果我有 40 列怎么办?我可以发GROUP BY p.*
吗?
@AlexanderKim:我不认为这是有效的语法。而且,一般来说,枚举列而不是使用*
是一种很好的做法(例如,这样可以避免在向表中添加新列时破坏查询结果)。
@AlexanderKim:这真的取决于你的数据集......你需要测试这两个选项,看看哪个表现更好。【参考方案2】:
如果image
的数据类型是varchar或int,那么不要加入表product_images
,而是加入每个产品图像的MIN:
SELECT p.*, i.image
FROM products p
LEFT JOIN (
SELECT product_id, MIN(image) image
FROM product_images
GROUP BY product_id
) i
ON p.id = i.product_id
ORDER BY created_at DESC
LIMIT $limit
【讨论】:
以上是关于MySQL Left join 无法在单个查询中删除重复项的主要内容,如果未能解决你的问题,请参考以下文章
Linq2Sql:即使返回单个记录,也始终执行 LEFT JOIN
Mysql 连接(left join, right join, inner join ,full join)