SQL分组查询问题:如何仅取service_frequency最小值并匹配对应quote_id
解决SQL分组获取最小service_frequency对应正确quote_id的问题
问题说明
需要从quotes表中按address_id分组,获取每个分组里service_frequency最小的完整记录,必须保证quote_id是该最小频率对应的真实ID,不能出现原SQL中「最小service_frequency+最小quote_id」的错误组合。
现有错误SQL
SELECT * FROM quotes QT INNER JOIN (SELECT address_id, min(service_frequency) AS MINFrequency, min(quote_id) as quote_id FROM quotes GROUP BY address_id) groupQT ON QT.address_id = groupQT.address_id AND QT.quote_id = groupQT.quote_id
当前意外输出
| quote_id | service_frequency | address_id |
|---|---|---|
| 1 | 4 | 3 |
| 2 | 3 | 2 |
| 3 | 1 | 1 |
预期输出
| quote_id | service_frequency | address_id |
|---|---|---|
| 6 | 3 | 3 |
| 5 | 1 | 2 |
| 3 | 1 | 1 |
可行解决方案
方案1:窗口函数(推荐)
用ROW_NUMBER()窗口函数给每个address_id分组内的记录按service_frequency升序编号,取编号为1的记录就是每组最小频率对应的那条:
SELECT quote_id, service_frequency, address_id FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY address_id ORDER BY service_frequency ASC) AS rn FROM quotes ) t WHERE rn = 1;
- 如果同一
address_id下有多个相同最小频率的记录,ROW_NUMBER()会只取一条;要是想保留所有符合条件的记录,把ROW_NUMBER()换成RANK()或DENSE_RANK()就行。
方案2:关联子查询
先通过子查询找出每个address_id的最小service_frequency,再关联原表匹配对应的完整记录:
SELECT QT.* FROM quotes QT INNER JOIN ( SELECT address_id, MIN(service_frequency) AS MINFrequency FROM quotes GROUP BY address_id ) groupQT ON QT.address_id = groupQT.address_id AND QT.service_frequency = groupQT.MINFrequency;
- 这个方案会返回同一
address_id下所有频率为最小值的记录,要是只需要一条,可以配合DISTINCT或者额外的排序逻辑。
原SQL错误原因
原SQL的子查询里同时对service_frequency和quote_id取最小值,这两个最小值来自分组内的不同记录,导致最终关联出来的是分组里最小的quote_id,而非最小service_frequency对应的那个quote_id,所以结果不符合预期。
内容的提问来源于stack exchange,提问作者Jackbeeby
相关产品推荐
相关产品推荐

