我试着用这个问题来理解LATERAL JOIN:

select m1.contributor_prescription, derniere_publication.date_publication_prescription 
from activite.metadonnee m1
left join lateral 
(select date_publication_prescription, m2.contributor_prescription 
from activite.metadonnee m2 
where m1.contributor_prescription = m2.contributor_prescription 
order by date_publication_prescription desc
limit 3) as derniere_publication
ON true
order by m1.contributor_prescription

目标是 for each contributor_prescription人提供3个最新的date_publication_prescription.

目前,结果是全部contributor_prescription行,最后date_publication_prescription行.

contributor_prescription date_publication_prescription
john 22/10/2023
john 22/10/2023
(as many times as john exists in the table)
paul 24/10/2023
paul 24/10/2023
(as many times as paul exists in the table)

expected:

contributor_prescription date_publication_prescription
john 22/10/2023
john 21/10/2023
john 20/10/2023
paul 24/10/2023
paul 23/10/2023
paul 21/10/2023

推荐答案

如果您想要最新的每contributor_prescription前3名,您可以用row_number()订购,然后使用普通的where:demo只保留前3名

with cte as (
    select contributor_prescription, 
           date_publication_prescription,
           row_number()over w1 as rn
    from activite.metadonnee m1
    window w1 as (partition by contributor_prescription
                      order by date_publication_prescription desc) )
select contributor_prescription,
       date_publication_prescription
from cte 
where rn<=3
order by 1,2 desc;
contributor_prescription date_publication_prescription
john 2023-10-22
john 2023-10-21
john 2023-10-20
paul 2023-10-24
paul 2023-10-23
paul 2023-10-21

或者could做你做过的事情,但不要直接连接到源表,而是连接到distinct contributor_prescription:

select m1.contributor_prescription, 
       derniere_publication.date_publication_prescription 
from (select distinct contributor_prescription from activite.metadonnee) m1
left join lateral 
(   select  date_publication_prescription, 
            m2.contributor_prescription 
    from activite.metadonnee m2 
    where m1.contributor_prescription = m2.contributor_prescription 
    order by date_publication_prescription desc
    limit 3) as derniere_publication
ON true
order by m1.contributor_prescription

否则,您要求每一行都向您显示具有相同contributor_prescription的最近3行,不必要地将所有内容相乘.请注意performance of that isn't great这个数字.

还有一种非常简单的方法,可以收集到一个数组中,获取一个切片并解嵌套:

select contributor_prescription, unnest(arr)
from (select contributor_prescription, 
            (array_agg(date_publication_prescription 
                       order by date_publication_prescription desc))[:3] arr
      from activite.metadonnee
      group by 1) a;

但表现最好的是声名狼藉的(still emulated)index skip scan:demo

WITH RECURSIVE t AS (
   SELECT contributor_prescription,
          1 as rank_pos,
          max(date_publication_prescription) AS date_publication_prescription
   FROM activite.metadonnee 
   GROUP BY contributor_prescription
   UNION ALL
   SELECT contributor_prescription,
          rank_pos+1,
          (SELECT max(date_publication_prescription) 
           FROM activite.metadonnee 
           WHERE date_publication_prescription < t.date_publication_prescription
           AND contributor_prescription=t.contributor_prescription)
   FROM t 
   WHERE rank_pos<3
   )
SELECT contributor_prescription, date_publication_prescription
FROM t;

Postgresql相关问答推荐

Postgr不列出运算符和函数

计算两个子查询之间的差异

PostgreSQL散列连接与嵌套循环和散列索引

时间戳的postgreSQL-to_char如果为零,则不显示微秒

如何重新格式化已获取的 psql 查询输出?

@符号在yacc中的函数中是什么意思

EF Core添加迁移目标postgreeSQL返回无法加载类型'Microsoft.EntityFrameworkCore.Storage.IRelationalValueBufferFactoryFactory

在 KnexJS 中插入

获取 OperationalError: FATAL: sorry, too many clients already using psycopg2

如何将 DELETE 的返回值插入到 postgresql 中的 INSERT 中?

在 PostgreSQL 中将时间转换为秒

为 postgresql 存储过程设置隔离级别

仅在存在时重命名列

Python PostgreSQL 模块.哪个最好?

PostgreSQL 中的行编号

pg_restore 会覆盖现有的表吗?

查询 JSON 列中的数组元素

从 5 分钟前的表中获取行

如何在 JPA 中使用 Postgres JSONB 数据类型?

postgres LISTEN/NOTIFY rails