如何实现SQL GROUP BY强制分组或指定优先选取可用值?
问题说明
现有两张表:
表1(T1):
| ID | AMOUNT | NUMBER |
|---|---|---|
| 1 | 100$ | 456 |
| 2 | 22$ | 789 |
表2(T2):
| NUMBER | VALUE (string) |
|---|---|
| 456 | abc |
| 456 | def |
| 789 | ghi |
使用以下查询语句:
SELECT DISTINCT T1.ID, T1.AMOUNT, T2.VALUE FROM T1 RIGHT JOIN T2 ON T1.NUMBER = T2.NUMBER
得到非预期结果(ID重复):
| ID | AMOUNT | VALUE |
|---|---|---|
| 1 | 100$ | abc |
| 1 | 100$ | def |
| 2 | 22$ | ghi |
尝试按ID GROUP BY时报错,需求是每个ID唯一,保留任意一个对应的VALUE,预期结果示例:
| ID | AMOUNT | VALUE |
|---|---|---|
| 1 | 100$ | abc |
| 2 | 22$ | ghi |
解决方案
方法1:聚合函数+GROUP BY
因为ID和AMOUNT是一一对应关系,同时按ID和AMOUNT分组,对VALUE取聚合值(比如MIN取字母序最小的,MAX取最大的,满足“任意可用VALUE”的需求):
SELECT T1.ID, T1.AMOUNT, MIN(T2.VALUE) AS VALUE FROM T1 RIGHT JOIN T2 ON T1.NUMBER = T2.NUMBER GROUP BY T1.ID, T1.AMOUNT
注:之前GROUP BY报错是因为多数数据库要求SELECT中的非聚合列必须出现在GROUP BY中,只GROUP BY ID的话,数据库无法确定AMOUNT的取值(尽管实际是一一对应),把ID和AMOUNT一起加入GROUP BY即可解决。
方法2:窗口函数(适用于支持ROW_NUMBER的数据库)
如果你的数据库支持窗口函数(如MySQL 8+、PostgreSQL、SQL Server等),用ROW_NUMBER()给每个ID下的VALUE编号,然后取编号为1的行:
SELECT ID, AMOUNT, VALUE FROM ( SELECT T1.ID, T1.AMOUNT, T2.VALUE, -- 按ID分组,给VALUE排序后编号,ORDER BY可控制取哪个VALUE,无所谓的话可省略或用ORDER BY NULL ROW_NUMBER() OVER (PARTITION BY T1.ID ORDER BY T2.VALUE) AS rn FROM T1 RIGHT JOIN T2 ON T1.NUMBER = T2.NUMBER ) AS sub_query WHERE rn = 1
内容的提问来源于stack exchange,提问作者Noé Ventura
相关产品推荐
相关产品推荐

