从子查询中的排序结果中获取前 X 行

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

我只想从表中选择那些包含在另一个子查询结果中的标识符,并且只能使用前 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
子句中?

postgresql subquery common-table-expression
1个回答
0
投票

您的查询似乎已损坏,我无法在您的版本中执行它 看起来应该是这样的

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

而且效果很好

rid|
---+
 41|
 42|

如果您发布表格数据以了解问题所在会更好

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