Postgresql

PostgreSQL 中的遞歸 CTE 以生成不同頻率的數據

  • January 8, 2022

我正在嘗試編寫一個在 Postgresql 14 中使用遞歸 CTE 的數據生成查詢。

考慮包含函式 getfreq 的模式“sc”。getfreq 將一個 int 作為參數(表示另一個表的外鍵),並返回一個 int 返回,它表示頻率。

現在考慮這個查詢:

WITH RECURSIVE rec AS 
(
SELECT 1 as fk FROM generate_series(1, sc.getfreq(1), 1)
UNION ALL
SELECT r.fk + 1 FROM rec AS r WHERE r.fk + 1 <= 10
)
select row_number() OVER () as pk, fk from rec

getfreq 期望從 1 到 10 的 int (因此 r.fk <= 10 退出條件)。它返回一個頻率 N。我希望遞歸 CTE 的每次迭代都創建 N 行。每次迭代的結果將由 UNION ALL 子句組合在一起。最後,我想要一個結果,其中行數等於 getfreq 在 10 次迭代中返回的頻率總和。

在上面的範例中,sc.getfreq(1) 將始終返回 5,因此我得到了 50 行的結果集;第一個 5 fk = 1,第二個 5 fk = 2,依此類推。但是,實際上應該使用迭代值呼叫 sc.getfreq(),因此第二次迭代應該是 sc.getfreq(2) 等等。自然,sc.getfreq(2) 將返回不同的頻率而不是 5,因此最終結果不應有 50 行。

我曾嘗試在 getfreq 中使用“fk”,如下所示: sc.getfreq(fk); 因為“fk”被 CTE 的遞歸部分遞增(因此在第二次迭代中為 2,在第三次迭代中為 3,依此類推),但列“fk”在 FROM 的上下文中不存在,大概是因為“SELECT”部分還沒有執行。

遞歸 CTE 適合解決這個問題嗎?我可以通過一些調整來實現我想要的嗎?

範例輸出,其中 getfreq(1) 返回 5,getfreq(2) 返回 2,getfreq(3) 返回 1。

……等等(這是3次迭代的不完整範例)。

我認為您不需要遞歸解決方案。

select 
   row_number() over (order by r.fk, s.p) as pk, 
   r.fk
from 
   generate_series(1, 10) as r (fk),
   generate_series(1, sc.getfreq(r.fk)) as s (p)
;

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