按父表限制内连接结果数量的SQL实现方法
没问题,这个需求用窗口函数就能轻松搞定,现在大部分主流数据库(像PostgreSQL、MySQL 8.0+、SQL Server这些)都支持这种写法,我给你一步步拆解:
核心思路
先把两张表关联,然后给每个区域对应的天气记录按规则编号,最后只保留编号小于等于你指定条数的记录。
通用实现(支持窗口函数的数据库)
假设你想每个区域最多返回2条天气记录,SQL代码如下:
SELECT w.id, w.temp, f.name AS freguesia_name FROM ( SELECT id, temp, id_freg, -- 按区域分组,给每组内的记录单独编号 ROW_NUMBER() OVER (PARTITION BY id_freg ORDER BY id) AS row_num FROM weathers ) w INNER JOIN freguesias f ON w.id_freg = f.id WHERE w.row_num <= 2; -- 这里的数字就是你要限制的每条区域的记录数
代码说明:
PARTITION BY id_freg:把天气记录按所属区域分组,确保每个区域的记录独立编号ORDER BY id:决定每个区域内记录的排序逻辑,你可以换成其他字段(比如如果有时间字段,想取最新的就用ORDER BY record_time DESC)- 子查询生成编号后,和区域表关联,再通过
WHERE w.row_num <= N筛选出每个区域的前N条记录
兼容老版本MySQL(无窗口函数)
如果你的MySQL版本低于8.0,不支持窗口函数,可以用关联子查询的方式实现:
SELECT w.id, w.temp, f.name AS freguesia_name FROM weathers w INNER JOIN freguesias f ON w.id_freg = f.id WHERE ( -- 统计同区域内id小于等于当前记录id的条数,相当于排序后的位置 SELECT COUNT(*) FROM weathers w2 WHERE w2.id_freg = w.id_freg AND w2.id <= w.id ) <= 2;
注意事项
- 排序规则一定要明确:如果不指定
ORDER BY,窗口函数生成的编号可能是随机的,务必根据你的业务需求选择排序字段(比如按温度、时间或者id) - 如果需要包含所有区域(哪怕没有对应的天气记录),把
INNER JOIN换成LEFT JOIN即可 - 如果你想返回每个区域的任意N条而不是按顺序的,也可以用
RAND()来排序,但性能会差一些,不建议大数据量使用
内容的提问来源于stack exchange,提问作者Hula Hula
相关产品推荐
相关产品推荐

