汇总 table 中的数据,直至 table 中每一行的日期

Aggregating data in a table up to the date of each row in the table

如果我 运行 以下查询,它会产生 160 万行:

SELECT 
    customer_id,
    credit_id,
    date
FROM 
    wallet
WHERE
    credit_title = 'Topups'
    AND credit_type = 'Credit Card Topups'
    AND day >= DATE '2017-11-06'
    AND day <= DATE '2020-04-03'

我现在正尝试为上述查询中的每一行获取该客户截至该行日期的所有信用交易的计数和总额。我已经尝试了下面的查询(这是一个与自身的连接),但这导致了 130 万行。为什么在连接中删除行? credit_id 是这个 table 中的唯一标识符。

SELECT
    customer_id,
    credit_id,
    COALESCE(COUNT(wallet_agg.credit_id), 0) AS topup_count_to_date,
    COALESCE(SUM(wallet_agg.credit_amt_usd), 0) AS topup_amount_to_date
FROM
    wallet
LEFT JOIN
    wallet AS wallet_agg
ON
    wallet.customer_id = wallet_agg.customer_id
    AND wallet_agg.date < wallet.date
WHERE
    wallet.credit_title = 'Topups'
    AND wallet.credit_type = 'Credit Card Topups'
    AND wallet.day >= DATE '2017-11-06'
    AND wallet.day <= DATE '2020-04-03'
    AND wallet_agg.credit_title = 'Topups'
    AND wallet_agg.credit_type = 'Credit Card Topups'

Here is a simple demo of what I am trying,得到了我期待的结果。我上面更复杂的查询的逻辑有何不同?

您的 JOIN 正在根据 WHERE 条件转变为内部联接。您需要将第二个 table 上的条件移动到 ON 子句中:

FROM wallet LEFT JOIN
     wallet AS wallet_agg
     ON wallet.customer_id = wallet_agg.customer_id AND
        wallet_agg.date < wallet.date AND
        wallet_agg.credit_title = 'Topups'
        wallet_agg.credit_type = 'Credit Card Topups'
WHERE wallet.credit_title = 'Topups' AND
      wallet.credit_type = 'Credit Card Topups' AND
      wallet.day >= DATE '2017-11-06' AND
      wallet.day <= DATE '2020-04-03'

当然,聚合对于这个问题来说有点过头了。您应该只使用 window 函数:

SELECT w.*
FROM (SELECT w.customer_id, w.credit_id, w.date,
             COUNT(*) OVER (PARTITION BY customer_id, credit_title, credit_type ORDER BY date) as topup_count_to_date,
             SUM(amount) OVER (PARTITION BY customer_id, credit_title, credit_type ORDER BY date) as topup_amount_to_date
      FROM wallet w
      WHERE w.credit_title = 'Topups' AND
            w.credit_type = 'Credit Card Topups' 
    ) w
WHERE w.day >= DATE '2017-11-06' AND
      w.day <= DATE '2020-04-03';