Kou*_*rev 157 sql postgresql
我需要为每个组取前N行,按自定义列排序.
鉴于下表:
db=# SELECT * FROM xxx;
id | section_id | name
----+------------+------
1 | 1 | A
2 | 1 | B
3 | 1 | C
4 | 1 | D
5 | 2 | E
6 | 2 | F
7 | 3 | G
8 | 2 | H
(8 rows)
Run Code Online (Sandbox Code Playgroud)
我需要每个section_id的前两行(按名称排序),即类似于的结果:
id | section_id | name
----+------------+------
1 | 1 | A
2 | 1 | B
5 | 2 | E
6 | 2 | F
7 | 3 | G
(5 rows)
Run Code Online (Sandbox Code Playgroud)
我正在使用PostgreSQL 8.3.5.
小智 260
新解决方案(PostgreSQL 8.4)
SELECT
*
FROM (
SELECT
ROW_NUMBER() OVER (PARTITION BY section_id ORDER BY name) AS r,
t.*
FROM
xxx t) x
WHERE
x.r <= 2;
Run Code Online (Sandbox Code Playgroud)
pos*_*est 21
从v9.3开始,你可以进行横向连接
select distinct t_outer.section_id, t_top.id, t_top.name from t t_outer
join lateral (
select * from t t_inner
where t_inner.section_id = t_outer.section_id
order by t_inner.name
limit 2
) t_top on true
order by t_outer.section_id;
Run Code Online (Sandbox Code Playgroud)
它可能更快,但当然,您应该专门针对您的数据和用例测试性能.
小智 14
横向联接是可行的方法,但您应该首先执行嵌套查询以提高大型表的性能。
SELECT t_limited.*
FROM (
SELECT DISTINCT section_id
FROM t
) t_groups
JOIN LATERAL (
SELECT *
FROM t t_all
WHERE t_all.section_id = t_groups.section_id
ORDER BY t_all.name
LIMIT 2
) t_limited ON true
Run Code Online (Sandbox Code Playgroud)
如果没有嵌套选择不同,即使section_id经常重复,横向连接也会针对表中的每一行运行。使用嵌套选择不同,连接横向对于每个不同的section_id运行一次且仅一次。
Kou*_*rev 10
这是另一个解决方案(PostgreSQL <= 8.3).
SELECT
*
FROM
xxx a
WHERE (
SELECT
COUNT(*)
FROM
xxx
WHERE
section_id = a.section_id
AND
name <= a.name
) <= 2
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
69180 次 |
| 最近记录: |