2014-02-16 76 views
1

我正在使用遞歸語句來選擇代表樹結構條目的表中給定父項的所有子項。這是在Sqlite(它現在支持遞歸)。
這使我可以非常快速地選擇樹中的數千條記錄,而不會因爲從調用應用程序準備數千條選擇語句而遭受巨大的性能損失。重複使用Sqlite中以下查詢中的SQL查詢的結果

WITH RECURSIVE q(Id) AS 
(
    SELECT Id FROM Entity 
    WHERE Parent=(?) 
    UNION ALL 
    SELECT m.Id FROM Entity AS m 
    JOIN Entity ON m.Id=q.Parent 
) 
SELECT Id FROM q; 

現在,假設我有任何數量的其他表中的這些實體的相關數據,我想隨後加載。由於它們的任意數量(以模塊化方式),因此不可能直接在這個數據中包含數據提取。他們必須遵循它。但是,如果對於每個相關的表,然後執行一條SELECT語句,那麼直接在Sqlite中直接從樹中選擇所有數據的所有性能增益幾乎是無用的,因爲我仍然會在數千個隨後的請求中停頓,併發出一個選擇語句。

所以兩個問題:

  1. 更好的解決辦法是制定一個類似遞歸的語句爲每個相關的表,這將遞歸地從這棵樹上再次聚集實體,這次選擇它們的相關數據加入它。 這聽起來確實更有效率,但制定這樣一個聲明真的很棘手,我在這裏有點失落。

  2. 現在真正的奧祕在於,會不會有一個更有效的解決方案,它將以某種方式將最後一個查詢的結果緩存到某處(實體樹中具有id的行)並將它們連接到在下面的語句中不需要遞歸迭代它呢?

這是第一個選項的嘗試,假設我想從相關表中選擇一個字段Data組件:是第二個UNION ALL合法嗎?

WITH RECURSIVE q(Data) AS 
(
    SELECT Id FROM Entity 
    WHERE Parent=(?) 
    UNION ALL 
    SELECT m.Id FROM Entity AS m 
    JOIN Entity ON m.Id=q.Parent 
    UNION ALL 
    SELECT Data FROM Component AS c 
    JOIN Component ON c.Id=q.Id 
) 
SELECT Data FROM q; 

回答

1

documentation說:

2.命名的AS關鍵字的左側必須從化合物的最右邊的SELECT語句的WHERE子句中出現一次表選擇,無處不在。

所以你的第二個查詢是不合法的。

但是,CTE的行爲像一個普通的表/視圖,所以你可以把它加入相關的表:

WITH RECURSIVE q(Id) AS 
(...) 
SELECT q.Id, c.Data 
FROM q JOIN Component AS c ON q.Id = c.Id 

如果你想重用q對多個查詢計算出的值,沒有什麼你可以用CTE來做,但你可以將它們存儲在臨時表中:

CREATE TEMPORARY TABLE q_123 AS 
WITH RECURSIVE q(Id) AS 
(...) 
SELECT Id FROM q; 

SELECT * FROM q_123 JOIN Component ...; 
SELECT * FROM q_123 JOIN Whatever ...; 

DROP TABLE q_123; 
+0

不錯!你認爲創建臨時表的這種用例(10 000條記錄)會比第一個選項更有趣嗎?我會嘗試這些解決方案並回復你 – MONK