2012-07-28 84 views
10

我遇到了一個案例,我期望返回一個錯誤的sqlite查詢實際上是成功的,我想知道是否有人可以指出爲什麼這個查詢是有效的。聯合所有與具有不同列數的查詢

CREATE TABLE test_table(
    k INTEGER, 
    v INTEGER 
); 

INSERT INTO test_table(k, v) VALUES(4, 5); 

SELECT * FROM(
    SELECT * FROM(
    SELECT k, v FROM test_table WHERE 1 = 0 
) 
    UNION ALL 
    SELECT * FROM(
    SELECT rowid, k, v FROM test_table 
) 
) 

sqlfiddle of above

我認爲unioning 2箇中選擇具有不同的列數將返回一個錯誤。如果我刪除最外層的SELECT *,則會收到我期待的錯誤:SELECTs to the left and right of UNION ALL do not have the same number of result columns

+0

看起來像SQLite的一個怪癖! – Andomar 2012-07-28 20:37:39

+0

奇怪 - 它返回什麼?缺少列的空值? – 2012-07-28 20:41:53

+0

哦,我檢查了演示,它省略了列。 – 2012-07-28 20:42:47

回答

10

答案似乎很簡單:是的,這是一個怪癖。 我想用一個簡短的例子來證明這一點。但事前,我們諮詢documentation

兩個或多個簡單的SELECT語句可以連接在一起,形成 複合SELECT使用UNION,UNION ALL,INTERSECT或EXCEPT 運營商。 在複合SELECT中,所有組成SELECT必須 返回相同數量的結果列。

所以文件說得非常清楚,兩個SELECTs必須提供相同數量的列。然而,正如你所說,最外層的SELECT奇怪地避免了這個「限制」。

實施例1

SELECT * FROM(
    SELECT k, v FROM test_table 
    UNION ALL 
    SELECT k, v,rowid FROM test_table 
); 

結果:

k|v 
4|5 
4|5 

第三列rowid被簡單地省略,如在註釋中指出。

實施例2

我們只切換所述兩個選擇語句的順序。

SELECT * FROM(
    SELECT k, v, rowid FROM test_table 
    UNION ALL 
    SELECT k, v FROM test_table 
); 

結果

k|v|rowid 
4|5|1 
4|5| 

現在,SQLite不省略列,但添加一個空值。

結論

這使我想起我的結論,那簡直sqlite的處理UNION ALL不同,如果它是作爲一個子查詢處理。 PS:如果你只是使用UNION,它會在任何情況下失敗。

7

UNION ALL將在額外的列中返回空值的結果。

基本的UNION將失敗,因爲沒有ALL的UNION必須具有來自兩個表的相同數量的列。

所以:

SELECT column1, column2 FROM table a 
UNION ALL 
SELECT column1, column2, column3 FROM table b 

回報3列與空列3

和:

SELECT column1, column2 FROM table a 
UNION 
SELECT column1, column2, column3 FROM table b 

應該失敗,因爲列數不匹配。

總之,您可以向UNION添加一個空白列,以便從每個表中選擇3列,它仍然可以工作。

EX:

SELECT column1, column2, '' AS column3 FROM table a 
UNION 
SELECT column1, column2, column3 FROM table b 
+0

好方法!! – 2016-03-17 00:22:23