【问题标题】:How to get a set of records from within each partition based on a condition如何根据条件从每个分区内获取一组记录
【发布时间】:2022-07-08 00:41:28
【问题描述】:

从这样的表中:

id status date category
1 PENDING 2022-07-01 XYZ
2 DONE 2022-07-04 XYZ
3 PENDING 2022-07-03 DEF
4 DONE 2022-07-08 DEF

我想获取每个类别中的最新记录(此处为 2 和 4)。但至少有两个因素使事情复杂化。

首先,同一类别中可能有两条以上的记录。 (记录成对出现。)

id status date category
1 PENDING 2022-07-01 XYZ
2 PENDING 2022-07-02 XYZ
3 FAILED 2022-07-04 XYZ
4 FAILED 2022-07-05 XYZ
5 PENDING 2022-07-03 DEF
6 DONE 2022-07-08 DEF

在这种情况下,我必须得到 3、4 和 6。如果 XYZ 类别中有 6 条记录,我必须得到最近的 3 条。

其次,一个类别中最新记录的日期可能相同。

我尝试过这样的事情:

WITH temp AS (
    SELECT *,
           dense_rank() OVER (PARTITION BY category ORDER BY date DESC) rnk
    FROM tbl
)
SELECT *
FROM temp
WHERE rnk = 1;

但是当一个类别中有超过 2 条记录时,这会失败,我需要获取最近的两条。

【问题讨论】:

  • 在第二张表中,为什么要使用id=3 记录XYZ?用id=4 记录更新? :-?
  • (1, 3) 和 (2, 4) 是对的。每对引用属于同一类别的不同消息,并及时跟踪该消息的状态。基本上,我想要的是获取每个类别中每条消息的最新状态。在第二个表中,XYZ 类别中有两条消息,它们的最新状态为 FAILED。我知道这是糟糕设计的征兆,但我必须接受它。
  • 您提出的问题依赖于了解配对信息,但您没有提出任何条件让我们知道哪些消息已配对。即使我们假设(您还没有说过)状态必须在该对中的两行之间发生变化,我们如何知道这一点,例如(1,4) 和 (2,3) 不是对吗?

标签: sql postgresql


【解决方案1】:

这里的要求更加硬编码,然后遵循适当的设计。 根据问题中提出的内容,我只是稍微调整了一下以获得最后的记录。

假设记录总是成对的,如问题中所述。

WITH temp AS (
    SELECT *,
           row_number() OVER (PARTITION BY category ORDER BY date1 DESC) rnk,
           count(1) over (partition by category) cnt
    FROM status
)
SELECT *
FROM temp
WHERE rnk*2 <= cnt;

参考小提琴here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2021-08-15
    • 2010-09-11
    • 2018-04-27
    相关资源
    最近更新 更多