Postgresql

當時間序列中的值為空時返回上一個執行總計

  • April 28, 2020

這是上一個問題的延續,其中可以找到表定義和範例數據。(非常感謝@Erwin Brandstetter 的幫助)。

所有這些都是在 PostgreSQL 11.5 DB 上完成的。

SELECT *
FROM   (
  SELECT the_day::date
  FROM   generate_series(timestamp '2020-01-01', date_trunc('day', localtimestamp), interval '1 day') the_day
  ) d 
LEFT   JOIN (
  SELECT customer_id
       , created_at::date AS the_day
       , sum(sum(t.amount) FILTER (WHERE stock_ticker = 'tsla')) OVER w AS tsla_running_amount
       , sum(sum(t.amount) FILTER (WHERE stock_ticker = 'goog')) OVER w AS goog_running_amount
  FROM   transactions t
  WHERE  created_at >= timestamp '2020-01-01'
  GROUP  BY customer_id, created_at::date
  WINDOW w AS (PARTITION BY customer_id ORDER BY created_at::date)
  ) t USING (the_day)
ORDER  BY customer_id, the_day;

當客戶一天沒有交易時,我需要能夠顯示該客戶當天的“最近”執行總計。

例如:

2020-01-01:客戶購買 5 個“tsla”,總餘額為 5。
2020-01-02:客戶不採取任何行動。目前總餘額顯示為 5。
2020-01-03:客戶賣出 2 個“tsla”,現在總餘額 3 個。
2020-01-04:客戶不採取任何行動。目前餘額仍顯示為 3。

目前,按照這種設置方式,客戶在沒有交易的那一天的記錄將作為餘額總計的 NULL 行返回。

我如何在他們沒有交易的日子裡顯示他們的“最近”執行餘額?

此查詢將為表中存在的所有客戶執行transactions(過去至少有一次交易)。

一種方法是在執行視窗函式(customer_id, the_day) 之前生成一行。像:

SELECT c.customer_id, d.the_day
    , sum(t.tsla_amount) OVER w AS tsla_running_amount
    , sum(t.goog_amount) OVER w AS goog_running_amount
FROM   (
  SELECT the_day::date
  FROM   generate_series(timestamp '2020-01-01'
                       , date_trunc('day', localtimestamp)
                       , interval '1 day') the_day
  ) d 
CROSS  JOIN (SELECT DISTINCT customer_id FROM transactions) c  -- !
LEFT   JOIN (
  SELECT customer_id
       , created_at::date AS the_day
       , sum(t.amount) FILTER (WHERE stock_ticker = 'tsla') AS tsla_amount
       , sum(t.amount) FILTER (WHERE stock_ticker = 'goog') AS goog_amount
  FROM   transactions t
  WHERE  created_at >= timestamp '2020-01-01'
  GROUP  BY customer_id, created_at::date
  ) t USING (customer_id, the_day)
WINDOW w AS (PARTITION BY customer_id ORDER BY the_day)
ORDER  BY customer_id, the_day;

db<>在這裡擺弄

如果表很大,並且只有相對較少的不同客戶,您可能需要優化性能。看:

但是你通常會有一個單獨的客戶表來處理……

如果您希望在客戶的第一次交易之前0而不是在行中,請添加. 像:NULLCOALESCE

SELECT c.customer_id, d.the_day
    , COALESCE(sum(t.tsla_amount) OVER w, 0) AS tsla_running_amount
    , COALESCE(sum(t.goog_amount) OVER w, 0) AS goog_running_amount
FROM ...

引用自:https://dba.stackexchange.com/questions/266009