溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

PostgreSQL DBA(35) - CTE

發(fā)布時(shí)間:2020-08-11 06:19:02 來(lái)源:ITPUB博客 閱讀:142 作者:husthxd 欄目:關(guān)系型數(shù)據(jù)庫(kù)

CTE(Common Table Expressions)是指使用WITH語(yǔ)句定義的通用表表達(dá)式。
如:


testdb=# explain verbose WITH t1 AS ( SELECT * FROM t_w1 WHERE t_w1.id % 4 = 0 ) SELECT * FROM t1 JOIN t_w2 as t2 ON t2.id = t1.id;
                                QUERY PLAN                                
--------------------------------------------------------------------------
 Hash Join  (cost=167.74..359.00 rows=76 width=70)
   Output: t1.id, t1.c1, t2.id, t2.c1
   Hash Cond: (t2.id = t1.id)
   CTE t1
     ->  Seq Scan on public.t_w1  (cost=0.00..166.50 rows=38 width=8)
           Output: t_w1.id, t_w1.c1
           Filter: ((t_w1.id % 4) = 0)
   ->  Seq Scan on public.t_w2 t2  (cost=0.00..153.00 rows=10000 width=8)
         Output: t2.id, t2.c1
   ->  Hash  (cost=0.76..0.76 rows=38 width=62)
         Output: t1.id, t1.c1
         ->  CTE Scan on t1  (cost=0.00..0.76 rows=38 width=62)
               Output: t1.id, t1.c1
(13 rows)

使用CTE可以:
1.增強(qiáng)SQL的可讀性:如上例所示,通過(guò)CTE,可以”模塊化”SQL語(yǔ)句,增強(qiáng)腳本可讀性
2.實(shí)現(xiàn)遞歸:通過(guò)增加RECURSIVE修飾符來(lái)引入它自己,從而實(shí)現(xiàn)遞歸

遞歸
遞歸通常用于處理邏輯上存在層次或樹狀結(jié)構(gòu)的數(shù)據(jù).
如:


drop table if exists t_cte;
create table t_cte(id varchar(10),parent_id varchar(10));
insert into t_cte values('1',NULL);
insert into t_cte values('11','1');
insert into t_cte values('12','1');
insert into t_cte values('111','11');
insert into t_cte values('112','11');
insert into t_cte values('121','12');

id為數(shù)據(jù)表的id,parent_id是該id的父id,通過(guò)該字段可找到對(duì)應(yīng)的父記錄,先要求打印這些數(shù)據(jù)的樹狀結(jié)構(gòu),相應(yīng)的SQL語(yǔ)句如下:


WITH RECURSIVE ret AS
(
  SELECT
    parent_id,
    id::text as name,
    id::text
  FROM  t_cte
  WHERE id = '1'
  UNION ALL
  SELECT
    t.parent_id,
    t.parent_id || ' > ' || t.id as name,
  t.id
  FROM ret
  JOIN t_cte t
  ON t.parent_id = ret.id
)
SELECT
  parent_id,
  name 
FROM ret;

WITH RECURSIVE語(yǔ)句包含兩個(gè)部分
1.non-recursive term(非遞歸部分)
即上例中的:


SELECT
    parent_id,
    id::text as name,
    id::text
  FROM  t_cte
  WHERE id = '1'

2.recursive term(遞歸部分)
即上例中的:


SELECT
    t.parent_id,
    t.parent_id || ' > ' || t.id as name,
  t.id
  FROM ret
  JOIN t_cte t
  ON t.parent_id = ret.id

執(zhí)行步驟如下
1.執(zhí)行non-recursive term。其結(jié)果作為recursive term中對(duì)ret的引用,同時(shí)將這部分結(jié)果放入工作表中
2.重復(fù)執(zhí)行如下步驟,直到工作表為空:用工作表的內(nèi)容替換遞歸的自引用(上例中的ret),執(zhí)行recursive term,并用該結(jié)果替換工作表

大凡遞歸, 必須有結(jié)束條件,工作表為空則是CTE Recursive的結(jié)束條件.就上例來(lái)說(shuō),


SELECT
    t.parent_id,
    t.parent_id || ' > ' || t.id as name,
  t.id
  FROM ret
  JOIN t_cte t
  ON t.parent_id = ret.id

返回為空時(shí),遞歸結(jié)束.

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI