SQL查询:如何选取唯一CategoryID并关联对应ProductName?
嘿,我懂你遇到的问题了——从有重复CategoryID的表格里,给每个唯一的CategoryID保留一条对应的ProductName对吧?看你给出的期望结果,应该是想要每个分类下任意一个产品(比如分组里按名称排序的第一条),下面给你分几种常用数据库的实现方案,应该能解决你的问题:
MySQL/MariaDB
这里有两种常用方法,看你对选取的ProductName有没有特定要求:
方法1:GROUP BY + 聚合函数(简单快速)
如果对选哪个ProductName没有严格要求(比如只要每个分类有一个就行,或者选名称字典序最小/最大的),用这个最直接:
SELECT MIN(ProductName) AS ProductName, CategoryID FROM your_table_name GROUP BY CategoryID ORDER BY CategoryID;
MIN(ProductName)会取每个CategoryID下字母顺序最小的产品名,刚好匹配你给出的示例结果(比如CategoryID=1里的Mac比Walker小)。要是想取最大的,把MIN()换成MAX()就行。
方法2:窗口函数ROW_NUMBER()(更灵活可控)
如果需要精确控制选分组里的哪一条(比如按名称排序取第一条,或者按其他字段排序),窗口函数是更好的选择:
SELECT ProductName, CategoryID FROM ( SELECT ProductName, CategoryID, ROW_NUMBER() OVER (PARTITION BY CategoryID ORDER BY ProductName) AS rn FROM your_table_name ) AS sub_query WHERE rn = 1 ORDER BY CategoryID;
PARTITION BY CategoryID负责按分类分组,ORDER BY ProductName决定分组内的排序规则,rn=1就筛选出每组的第一条数据,完全符合你的期望结果。
SQL Server
SQL Server的方案和MySQL类似,另外还有个简洁的TOP 1 WITH TIES写法:
方法1:窗口函数(通用写法)
SELECT ProductName, CategoryID FROM ( SELECT ProductName, CategoryID, ROW_NUMBER() OVER (PARTITION BY CategoryID ORDER BY ProductName) AS rn FROM your_table_name ) AS sub_query WHERE rn = 1 ORDER BY CategoryID;
方法2:TOP 1 WITH TIES(简洁版)
SELECT TOP 1 WITH TIES ProductName, CategoryID FROM your_table_name ORDER BY ROW_NUMBER() OVER (PARTITION BY CategoryID ORDER BY ProductName);
这个写法一步到位,TOP 1 WITH TIES会返回所有分组中排第一的行,省去子查询的步骤。
PostgreSQL
PostgreSQL有个特有的DISTINCT ON语法,写起来非常简洁:
SELECT DISTINCT ON (CategoryID) ProductName, CategoryID FROM your_table_name ORDER BY CategoryID, ProductName;
DISTINCT ON (CategoryID)确保每个CategoryID只出现一次,后面的ORDER BY先按分类排序,再按ProductName排序,这样就会自动取每个分类里排序后的第一条数据。
⚠️ 别忘了把上面所有代码里的your_table_name替换成你实际的表名哦!之前Stack Overflow的方案没用,大概率是没选对适合你所用数据库的方法,或者排序条件没和你的需求匹配上,试试上面的方案应该能解决问题。
内容的提问来源于stack exchange,提问作者ghost deathrider

