在主表中每行查找N个最新行

问题描述 投票:0回答:2

对于表

line
中的每一行,表
line_version
中可以有很多行。我只需要为每个
line
行找到 N(比方说 2)“最新”行。这里的最新是指最大的ID。

例如,这就是

line_version
表行的样子(
line_id
引用
line
表):

  id   | line_id 
-------+---------
 10    |   1
 20    |   1
 30    |   1
 40    |   1
 50    |   2
 60    |   2
 70    |   2

查找每

line_version
行最新的 2 个
line
行 ID,应该是
(30, 40, 60, 70)

在全球范围内,我只需执行以下操作即可获得 2 个最新的:

SELECT id from line_version ORDER BY id DESC LIMIT 2

但是我怎样才能获得最新的2个

line_id

sql postgresql greatest-n-per-group
2个回答
0
投票

您可以使用下面的条件 rownumber>=count1-(N-1)。sql 小提琴here。对于最后一行,您可以使用 rownumber>=count1。最后两行 rownumber>=count1-1,三行 rownumber >=计数1-2

with data as (select 

     10 id   ,  1 line_id union all
     select 20    ,   1 union all
     select 30    ,   1 union all
     select 40    ,   1 union all
     select 50    ,  2 union all
     select 60    ,   2 union all
    select  70    ,   2),
    subset as (select a.*,ROW_NUMBER() over(partition by line_id order by id ) rownumber,count(id) over(partition by line_id) count1 from data a)
    select id,line_id from subset where rownumber>=count1-1;

为了提高性能,您可以使用下面的 rownumber 来取消 count1 <=N.

        with data as (select 

     10 id   ,  1 line_id union all
     select 20    ,   1 union all
     select 30    ,   1 union all
     select 40    ,   1 union all
     select 50    ,  2 union all
     select 60    ,   2 union all
    select  70    ,   2),
    subset as (select a.*,ROW_NUMBER() 
    over(partition by line_id order by id desc) 
    rownumber from data a)
    select id,line_id from subset 
    where rownumber<=2 order by line_id,id;

0
投票

如果版本数量远多于每行两个版本,请避免对

line_version
进行顺序扫描。这个使用
LATERAL
子查询的查询就是这样做的,并且应该更高效:

SELECT lv.*
FROM   line l
CROSS  JOIN LATERAL (
   SELECT lv.id
   FROM   line_version lv
   WHERE  lv.line_id = l.line_id
   ORDER  BY lv.id DESC NULLS LAST
   LIMIT  2  -- your pick!
   ) lv
-- ORDER BY ???

小提琴

我添加

NULLS LAST
主要是为了防止可能出现的空值,您尚未排除这种情况。参见:

确保 line_version 上有

index
,并以
line_id
作为前导索引字段。理想情况下:

CREATE INDEX line_version_line_id_id_idx ON line_version(line_id DESC NULLS LAST) INCLUDE (id);

参见:

© www.soinside.com 2019 - 2024. All rights reserved.