2012-10-17 73 views
2

我有一個數據記錄應用程序使用sqlite3來存儲不同類型的記錄共享一個共同的標題。SQLite中的有效變體記錄選擇/加入或條款

我把標題放在一個表中,併爲每個變體的細節創建單獨的表。

詳細表中的rowid是表頭的rowid。標題rowid僅顯示在其中一個詳細信息表中(對於該變體)。

我想在單個查詢中獲取多種類型的記錄。 也就是說,我希望Sqlite對標題表執行索引搜索以查找一組可用的記錄,然後使用該組標識對rowid進行變體細節的快速二進制提取。所以:

SELECT * FROM headers JOIN headers 
ON headers.id = variant1.id OR headers.id = variant2.id 
WHERE some_header_condition 

SELECT * FROM headers JOIN headers 
ON headers.id IN (variant1.id, revariant2.id) 
WHERE some_header_condition 

這工作,但與一個或詞語在JOIN謂詞面對,sqlite3的確實細節表VARIANT1和VARIANT2的全表掃描,而不僅僅是獲取由rowid外鍵記錄相應的記錄。

喜歡的東西:

0  0    2  SCAN TABLE variant2 (~5900 rows) 
0  1    1  SCAN TABLE variant1 (~26588 rows) 
0  2    0  SEARCH TABLE headers USING INTEGER PRIMARY KEY (rowid=?) (~2 rows) 
0  0    0  EXECUTE LIST SUBQUERY 1 

我可以做的技巧,比如強制使用二進制搜索:

SELECT header.f1, variant1.f, NULL FROM header JOIN header.id = variant1.id ... 
UNION ALL 
SELECT header.f1, NULL, variant2.f FROM header JOIN header.id = variant2.id ... 

但隨後的頭表被訪問兩次。

我也可以想象選擇header.id(s)到一個臨時表,並使用它來獲取使用它的ID的細節。

或......我可以將整個混亂解除規範。

但是所有這些解決方法都非常不方便。所以我的問題是,是否有一個很好的JOIN查詢,可以在沒有表掃描的情況下一次性提取這些變體?

回答

2

嘗試使用外連接:

SELECT * 
FROM headers 
    LEFT JOIN variant1 ON headers.id = variant1.id 
    LEFT JOIN variant2 ON headers.id = variant2.id 
WHERE headers... 

造成這樣的計劃:

sele order from deta 
---- ----- ---- ---- 
0  0  0  SEARCH TABLE headers USING INTEGER PRIMARY KEY (rowid>? AND rowid<?) (~31250 rows) 
0  1  1  SEARCH TABLE variant1 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows) 
0  2  2  SEARCH TABLE variant2 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows) 
+0

完美。謝謝。我想我嘗試了左連接,但我從來沒有嘗試將多個左連接鏈接在一起以擺脫或術語。 (看起來像大多數例子都不會超過2個表格!)這種語法仍然感覺有點不熟悉,但它工作得很好。 – PatchyFog