查询前10个出版物及其分类时出现重复行的问题
这个问题很常见——因为你的Publication和PublicationCategory是一对多的关联关系,当你用LEFT JOIN连接两张表时,每个关联的分类都会生成一条独立的结果行,所以同一个出版物会被重复返回多次(对应它的每个分类)。
下面给你两种常用的解决思路,根据你的需求选就行:
1. 把同一出版物的分类合并成单个字段(推荐,保留所有分类信息)
这种方法会把每个出版物的所有CategoryId合并成一个逗号分隔的字符串,这样每个出版物只会返回一行,同时不会丢失分类信息。不同数据库的语法略有区别:
SQL Server(2017及以上版本)
SELECT TOP 10 p.Id, p.Title, p.Content, STRING_AGG(pc.CategoryId, ', ') AS CategoryIds FROM [Publication] p LEFT JOIN [PublicationCategory] pc ON p.Id = pc.PublicationId GROUP BY p.Id, p.Title, p.Content ORDER BY p.Id;
MySQL
SELECT p.Id, p.Title, p.Content, GROUP_CONCAT(pc.CategoryId SEPARATOR ', ') AS CategoryIds FROM Publication p LEFT JOIN PublicationCategory pc ON p.Id = pc.PublicationId GROUP BY p.Id, p.Title, p.Content ORDER BY p.Id LIMIT 10;
PostgreSQL
SELECT p.Id, p.Title, p.Content, STRING_AGG(pc.CategoryId::TEXT, ', ') AS CategoryIds FROM "Publication" p LEFT JOIN "PublicationCategory" pc ON p.Id = pc.PublicationId GROUP BY p.Id, p.Title, p.Content ORDER BY p.Id LIMIT 10;
2. 只保留每个出版物的一行(适合仅需单个分类的场景)
如果你只需要每个出版物的任意一个分类,可以用窗口函数给每个出版物的行编号,然后只取编号为1的行:
WITH RankedPublications AS ( SELECT p.Id, p.Title, p.Content, pc.CategoryId, -- 按分类ID排序,确保每个出版物只取第一个分类 ROW_NUMBER() OVER (PARTITION BY p.Id ORDER BY pc.CategoryId) AS rn FROM [Publication] p LEFT JOIN [PublicationCategory] pc ON p.Id = pc.PublicationId ) SELECT Id, Title, Content, CategoryId FROM RankedPublications WHERE rn = 1 ORDER BY Id -- 注意:SQL Server用TOP 10,MySQL/PostgreSQL用LIMIT 10 LIMIT 10;
需要注意的是,第二种方法会丢弃该出版物的其他分类信息,所以如果需要完整的分类列表,第一种合并的方法是更好的选择。
内容的提问来源于stack exchange,提问作者Juanker
相关产品推荐
相关产品推荐

