在SQL语句中使用子查询的替代方法?

时间:2011-04-12 18:15:23

标签: sql query-optimization subquery

我有两张桌子:

TableA: (a temporary table)
ItemId (int)

TableB:
ItemId (int), ParentID (int)

我想检索表A中的所有项目,其中表A中任何项目的ParentID不作为ItemID存在。 (即我想获得TableA中项目的根目录)

此查询执行我想要的操作:

SELECT a.ItemID
FROM TableA a
INNER JOIN TableB b ON a.ItemId = b.ItemID
WHERE b.ParentID NOT IN ( SELECT * from TableA ) 

就像这一样:

SELECT b.ItemID 
FROM TableB b
WHERE b.ItemID IN ( SELECT * FROM TableA)
AND b.ParentID NOT IN ( SELECT * FROM TableA )

我对其中任何一个查询都不满意,特别是因为使用了NOT IN / IN。没有它们有没有办法做到这一点?也许更简洁的方式不需要子查询?

示例数据:

Table A
-------
2
3
5
6

Table B
--------
1 | NULL
2 | 1
3 | 1
4 | 3
5 | 3
6 | 3

期望的结果:

2
3

由于

4 个答案:

答案 0 :(得分:4)

查看Select all rows from one table that don't exist in another table,了解使用

进行此类查询的5种不同方法

不在 不存在
左和右连接
外部申请(2005年)) 除外(2005 +)

这是一个可以运行的脚本

CREATE TABLE #TableA( ItemId int)

INSERT #TableA values(1)
INSERT #TableA values(2)
INSERT #TableA values(3) 
INSERT #TableA values(4)
INSERT #TableA values(5)
INSERT #TableA values(6) 


CREATE TABLE #TableB( ItemId int, ParentID int)
INSERT #TableB values(1,1)
INSERT #TableB values(2,2)
INSERT #TableB values(4,3)
INSERT #TableB values(5,4)

这将为父母

SELECT a.ItemID
FROM #TableA a
LEFT JOIN #TableB b ON a.ItemId = b.ParentID
WHERE b.ItemID IS NULL

SELECT a.ItemID
FROM #TableA a
WHERE NOT EXISTS (SELECT 1 FROM #TableB b WHERE a.ItemId = b.ParentID)

输出

ItemID
5
6

答案 1 :(得分:4)

没有子查询:

SELECT ItemID
  FROM TableA
INTERSECT 
SELECT b.ItemID
  FROM TableB AS b
       LEFT OUTER JOIN TableA AS a
          ON b.ParentID = a.ItemID
 WHERE a.ItemID IS NULL;

...但你对子查询的恐惧是否理性? :)我发现这个等效的查询更容易阅读和理解:

SELECT ItemID
  FROM TableA
INTERSECT 
SELECT ItemID
  FROM TableB
 WHERE NOT EXISTS (
                   SELECT * 
                     FROM TableA AS a
                    WHERE a.ItemID = TableB.ParentID
                  );

答案 2 :(得分:0)

您可以使用外连接。像这样:

SELECT a.ItemID
FROM TableA a
INNER JOIN TableB b ON a.ItemId = b.ItemID
LEFT JOIN TableB parentB on a.ItemID = parentB.ParentID 
WHERE parentB.ParentID IS NULL 

答案 3 :(得分:0)

您的表A和B似乎存储了树结构。我将表A解释为"节点" (存储树的元素)和表B为"边缘" (将节点链接到它的父节点)。内部连接变体非常优雅,因为它涵盖了所有的情况,没有边缘到父母","边缘到PrantID null"和"边缘到不存在的父母"立刻。 欢呼声