将all与具有不同列数的查询联合起来

时间:2012-07-28 20:35:20

标签: sql sqlite

我遇到一个案例,我希望返回错误的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

我认为联合两个具有不同列数的选择将返回错误。如果我删除最外面的SELECT *,那么我会收到我期望的错误:SELECTs to the left and right of UNION ALL do not have the same number of result columns

3 个答案:

答案 0 :(得分:11)

答案似乎很简单:是的,这是一个怪癖。 我想用一个简短的例子来证明这一点。但事先,请参考documentation

  

两个或多个简单的SELECT语句可以连接在一起形成   使用UNION,UNION ALL,INTERSECT或EXCEPT的复合SELECT   运营商。   在复合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语句的顺序。

 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不会省略该列,而是添加一个空值。

<强>结论

这让我得出结论,如果将UNION ALL作为子查询处理,sqlite只会处理UNION

PS:如果您只是使用{{1}},它在任何情况下都会失败。

答案 1 :(得分:9)

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

答案 2 :(得分:2)

如果第二个查询的列数较少,则可以执行以下操作:

select col1, col2, col3, col4, col5
from table A

union all

select col1, col2, col3, col4, NULL as col5, 
from table B

除了NULL,还可以使用一些字符串常量-'KPI' as col5