簡體   English   中英

關於WITH RECURSIVE查詢Postgres的可能解釋

[英]Possible explanation on WITH RECURSIVE Query Postgres

我一直在閱讀Postgres中的With Query。 這就是我很驚訝的地方

WITH RECURSIVE t(n) AS (
    VALUES (1)
  UNION ALL
    SELECT n+1 FROM t WHERE n < 100
)
SELECT sum(n) FROM t;

我不明白查詢的評估如何工作。

  • t(n)聽起來像是帶有參數的函數。 n的值如何傳遞。

關於SQL遞歸語句如何分解的任何見解。

這稱為公用表表達式,是在SQL中表示遞歸查詢的一種方式:

t(n)將CTE的名稱定義為t ,其中有一列稱為n 它類似於派生表的別名:

select ... 
from (
  ...
) ;

遞歸以值1(即values (1)一部分)開始,然后遞歸地將values (1) ,直到達到99。 因此它將生成從1到99的數字。然后最終查詢將所有這些數字相加。

n是列名, 而不是 “變量”,並且“賦值”的發生方式與任何數據檢索相同。

WITH RECURSIVE t(n) AS (
    VALUES (1) --<< this is the recursion "root"
  UNION ALL
    SELECT n+1 FROM t WHERE n < 100 --<< this is the "recursive part"
)
SELECT sum(n) FROM t;

如果您“展開”遞歸(實際上是一個迭代),那么您將得到如下結果:

select x.n + 1
from (
  select x.n + 1
  from (
    select x.n + 1
    from (
      select x.n + 1
      from (
         values (1)
      ) as x(n) 
    ) as x(n)
  ) as x(n)
) as x(n)

手冊中的更多詳細信息:
https://www.postgresql.org/docs/current/static/queries-with.html

如果您正在尋找評估方式,則遞歸分為兩個階段。

  1. 根執行一次。
  2. 遞歸部分一直執行到沒有行返回為止。 關於這一點,文檔有點模糊。

現在,通常在數據庫中,我們對“功能”的思考方式與我們進行命令式編程時所想到的方式不同。 用數據庫術語來說,想到一個函數的最佳方法是“一種對應關系,對於每個域值,您都具有一個對應的值。” 因此,當前的挑戰之一是停止就編程功能進行思考。 甚至用戶定義的函數也最好用這種其他方式來考慮,因為它避免了在運行查詢和查詢計划程序的交集方面的許多潛在麻煩。因此,它看起來像一個函數,但這是不正確的。

相反,WITH子句使用不同的,幾乎相反的符號。 在這里,您具有集合名稱t ,后跟(在這種情況下為可選)元組結構(n) 因此,這不是具有參數的函數,而是與結構的關系。

因此,如何分解:

SELECT 1 as n where n < 100
UNION ALL
SELECT n + 1 FROM (SELECT 1 as n) where n < 100
UNION ALL
SELECT n + 1 FROM (SELECT n + 1 FROM (SELECT 1 as n)) where n < 100

當然,這是一個簡化,因為在內部我們會跟蹤cte狀態並保持對最后一次迭代的參與,因此在實踐中,它們會折回到接近線性的復雜度(而上圖顯示的性能要差得多)。

因此,實際上您會得到更多類似的信息:

 SELECT 1 as n where 1 < 100
 UNION ALL
 SELECT 1 + 1 as n where 1 + 1 < 100
 UNION ALL
 SELECT 2 + 1 AS n WHERE 2 + 1 < 100
 ...

本質上,以前的值會保留下來。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM