SQL Union的替代方法

时间:2018-07-02 12:40:44

标签: sql-server union

我有一个数字清单。我想从三个表的列表中确定它们在哪个表中,并在单个结果集中返回表名和编号。

Nums: 1,2,3,4,8,9
Tables: tb1, tb2, tb3

通常,我会查询每个表并将它们全部Union一起查询,但是我想知道是否有一种方法可以使语句使列表更小,因为它有望在很大程度上提高效率。数据。这是我想做的一个例子:

Checking tb1 first, I find that 1,2,3 are present.
Then check tb2 for the remaining numbers (4,8,9).
If none of the numbers are found, then check tb3, otherwise the query should end.

以下是两种可能的回报:

TableName | Num        *|*       TableName | Num
----------------       *|*       ----------------
tb1       | 1          *|*       tb1       | 1
tb1       | 2          *|*       tb1       | 2
tb1       | 3          *|*       tb1       | 3
tb3       | 4          *|*       tb2       | 4
tb3       | 8          *|*       tb3       | 9
tb3       | 9          *|*       *** 8 wasn't found

有没有办法做到这一点?还是Union还是最好的方法?

1 个答案:

答案 0 :(得分:1)

只是为了好玩,我编写了两个查询,一个使用UNION方法,另一个尝试使用上面定义的逻辑,即检查table1,然后在table2中查找其余项,然后在table3中查找,依此类推

这是我的脚本:

DECLARE @table1 TABLE (id INT PRIMARY KEY);
DECLARE @table2 TABLE (id INT PRIMARY KEY);
DECLARE @table3 TABLE (id INT PRIMARY KEY);
INSERT INTO @table1 SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 9;
INSERT INTO @table2 SELECT 3 UNION ALL SELECT 4;
INSERT INTO @table3 SELECT 6 UNION ALL SELECT 8;
SELECT id, 'table1' AS found FROM @table1 WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9)
UNION
SELECT id, 'table2' AS found FROM @table2 WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9)
UNION
SELECT id, 'table3' AS found FROM @table3 WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9)
ORDER BY id;

DECLARE @search TABLE (id INT PRIMARY KEY);
INSERT INTO @search SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9;
WITH 
    nt1 AS (SELECT * FROM @search s EXCEPT SELECT * FROM @table1),
    nt2 AS (SELECT * FROM nt1 EXCEPT SELECT * FROM @table2)
SELECT s.id, 'table1' AS found FROM (SELECT * FROM @search INTERSECT SELECT * FROM @table1) s
UNION ALL
SELECT s.id, 'table2' AS found FROM (SELECT * FROM nt1 INTERSECT SELECT * FROM @table2) s
UNION ALL
SELECT s.id, 'table3' AS found FROM (SELECT * FROM nt2 INTERSECT SELECT * FROM @table3) s
ORDER BY id;

每种方法的结果都相同,请注意这不会告诉您不匹配的地方,所以可能不是理想的选择吗?

然后,我将整个脚本视为执行计划。这不是火箭科学,并且有一个很强的论点是,引入新的@search表是“欺骗”,而且使用表变量来保存数据是错误的(即使是临时表也应使用物理表) ,并且表中的数据量太小等等。

但是,在这个有缺陷的实验中,我发现UNION方法的速度是后者的两倍以上。