我只想从另一个子查询结果中包含的表中 Select 那些标识符,并且只能使用前2行.

例如,您可以在PG上运行查询:

select a.rid 
from(
    values (41), (42), (43), (44)
    ) a(rid)
where a.rid in
(
select b.x
from(
    values (43), (44), (42), (41)
    ) b(x)
    order by b.x
fetch first 2 rows only
);

它应该返回

41
42

有时灵然而,如果我使用以下查询来处理CTE

select rid 
from(
    values (41), (42), (43), (44)
    ) s(rid)
where rid in 
(
with recursive messages as (
    select
        rid as "root_id",
        parent.id,
        parent.sent_date
    from
        purchase_message parent
    where
        parent.id = rid
union
    select
        rid as "root_id",
        child.id,
        child.sent_date
    from
        purchase_message child
    join messages on
        child.parent_message_id = messages.id 
    ),
ordered_root_ids as (
        select
        m."root_id",
        max(m."sent_date") over (partition by m."root_id") as "maxSentDate"
    from
        messages m
            order by "maxSentDate" desc
    )
    select "root_id" from ordered_root_ids
    fetch first 2 rows only
)

它不起作用.我得到所有结果

41, 42, 43, 44

为什么它不只返回2个结果? 根据我的预期,它必须只有2个结果,而且必须是43和44,因为它们是最新的消息.

我不知道如何提供所有相关表,因为太多了.我希望它们没有必要.CTE、循环CTE或嵌套查询是否会影响这一点?或者所有这些的组合?如何修改上述查询,使其对子查询中的数据进行排序,取顶部2行,然后将它们用于外部查询的in分句?

推荐答案

CTE、循环CTE或嵌套查询是否会影响这一点?或者所有这些的组合?

不是的limit 2fetch first 2 rows only没有办法只返回两行之外的内容.尽管如此,您仍会判断2行for each value,因此已经足够了.这:

select rid 
from(
    values (41), (42), (43), (44)
    ) s(rid)
where rid in 
(--parenthesized subexpression

将 for each rid独立运行带括号的子运算式,就像lateral子查询一样,因为您引用了其中的外部rid.因此,对于您判断的每个值,您最多会得到两个匹配项.我猜您预计只会获得2个匹配项一次,并且in()会将每个值与这两个值进行比较.

您可以将输入移动到CTE,然后从子查询中一次引用其所有rid,让它们都向下下降,一起排序,然后一起过滤到前2名.Demo at db<>fiddle:

with inputs(rid) as (values (41), (42), (43), (44) )
select rid 
from inputs join
(   with recursive messages as (
        select parent.id as "root_id",
               parent.id,
               parent.sent_date
        from purchase_message parent
        where parent.id in (select rid from inputs)
        union
        select parent."root_id",
               child.id,
               child.sent_date
        from purchase_message child
        join messages parent
          on child.parent_message_id = parent.id 
        )
    select m."root_id" as rid
    from messages m
    group by m."root_id"
    order by max(m."sent_date") desc
    fetch first 2 rows only
)q using(rid);
rid
43
44

我还必须改变您的逻辑,即根据分层 struct 中最近的sent_date名 Select 前两名root_id名.一旦允许它对所有输入rid进行操作,您的代码将继续 Select 相同rid中的2个:

ordered_root_ids as (
    select
        m."root_id",
        max(m."sent_date") over (partition by m."root_id") as "maxSentDate"
    from
        messages m
    order by "maxSentDate" desc
)
select "root_id" from ordered_root_ids
fetch first 2 rows only

由于您使用了窗口函数,您将获得每个层次 struct 的所有行,每一行重复其max(sent_date)行.只要具有最近sent_date的层次 struct 中有2行或更多行,您就会得到这两行,因为它们都具有相同的max(sent_date)和相同的rid.

Postgresql相关问答推荐

如何使用Docker安装PostgreSQL扩展

PostgreSQL:如何 for each 唯一的客户输入/更新列中的数据,并将其递增1直到表的末尾

为什么Postgres优化器切换到嵌套循环进行连接?

使函数内部动态插入更具可读性

仅使用 ssl 连接到 Postgresql 数据库

在 Postgres 中,部分索引比普通索引需要更多的时间和成本来执行

使用 pgx 扫描范围类型

求和直到达到一个值 postgresql

我在try 访问我的数据库表时在 postgresql 中收到 aclcheck_error 错误

为什么我使用 VBA 只能从 postgres 获得 10 行?

我应该 Select 哪种数据类型?

在 Ubuntu 11.04 服务器中启用对 postgresql 的 PHP 支持

在 to_tsquery 中转义特殊字符

为什么 PostgreSQL 将用户和组合并为角色?

断言错误:Django-rest-Framework

在函数中返回字段作为插入结果

为什么 PostgreSQL 数组访问在 C 中比在 PL/pgSQL 中快得多?

错误:ERROR: table name specified more than once

学习 PL/pgSQL 的好资源?

使用 Postgres 在 Rust 的 Diesel 库中添加时间戳