PostgreSQL中查询每个账号的最新和最新前的数据

问题背景

有时候我们需要PostgreSQL中查询每个账号的最新和最新前的数据,也就是Rank1+2的数据供使用。

解决方案

如果PostgreSQL中查询每个账号的最新和最新前的数据,我们可以使用窗口函数来实现。窗口函数允许我们对数据进行分区,然后在每个分区内执行计算。这里,我们可以使用ROW_NUMBER()窗口函数来为每个账号的记录分配一个唯一的行号,其中最新的记录将被分配行号1,最新前的数据将被分配行号2。

以下是一个SQL查询示例,它将返回每个账号的最新和最新前的数据:

SELECT *
FROM (
    SELECT
        account_id,
        transaction_date,
        amount,
        ROW_NUMBER() OVER (PARTITION BY account_id ORDER BY transaction_date DESC) AS rn
    FROM account_transactions
) AS subquery
WHERE rn <= 2;

这个查询的工作原理如下:

  1. PARTITION BY account_id告诉ROW_NUMBER()函数将数据按照account_id进行分区。
  2. ORDER BY transaction_date DESC确保在每个分区内,记录是按照transaction_date降序排序的,这样最新的记录将排在前面。
  3. ROW_NUMBER()为每个分区内的每一行分配一个唯一的行号,最新的记录将被分配行号1。
  4. 外层查询通过WHERE rn <= 2条件过滤出行号为1和2的记录,即每个账号的最新和最新前的数据。

请注意,这个查询假设account_transactions表中有一个account_id列(账号ID)、transaction_date列(交易日期)和amount列(金额)。如果你的表结构不同,你需要根据实际情况调整上述查询。

此外,如果你需要标记每条记录是最新记录还是最新前的数据,你可以使用CASE语句来添加一个额外的列来表示这个信息,如下所示:

--by https://zhengkai.blog.csdn.net
SELECT
    account_id,
    transaction_date,
    amount,
    CASE WHEN rn = 1 THEN 'Latest'
         WHEN rn = 2 THEN 'Second Latest'
    END AS record_type
FROM (
    SELECT
        account_id,
        transaction_date,
        amount,
        ROW_NUMBER() OVER (PARTITION BY account_id ORDER BY transaction_date DESC) AS rn
    FROM account_transactions
) AS subquery
WHERE rn <= 2;

这个查询将返回每个账号的最新和最新前的数据,并在record_type列中标记每条记录是最新记录还是最新前的数据。