我发现this tutorial关于SQL EXISTS运算符。我试图了解我们为什么需要它。 始终可以用另一个表达式替换“ EXISTS”(如下所示)
例如,此SQL:
SELECT count(SupplierName)
FROM Suppliers
WHERE EXISTS (SELECT * FROM Products WHERE SupplierId = Suppliers.supplierId AND Price < 20);
可以替换为此SQL:
SELECT count(SupplierName)
FROM Suppliers
WHERE (SELECT count(*) FROM Products WHERE SupplierId = Suppliers.supplierId AND Price < 20) > 0;
我对其进行了测试,并得到了相同的结果。
在任何情况下我们都必须使用“ EXISTS”吗?
答案 0 :(得分:3)
在您的示例中,EXISTS
效率更高。子查询需要读取所有个匹配行以进行计数。
EXISTS
可以(并且确实!)停在匹配的第一行。
您可能会说SQL引擎可以识别这种情况。但是,对于更复杂的查询,这将非常非常困难。
与您的观点相反,我发现EXISTS
比IN
或具有聚合功能的相关子查询还要有用。这是表达此逻辑的首选方法。
答案 1 :(得分:0)
在性能方面,EXISTS更好,因为它只需要检索单行而不是枚举所有行。
http://sqlblog.com/blogs/andrew_kelly/archive/2007/12/15/exists-vs-count-the-battle-never-ends.aspx
答案 2 :(得分:0)
在某些情况下,Exist可能会有更好的性能。 例如,要执行以下查询,引擎必须计算子查询中的所有行:
SELECT count(SupplierName)
FROM Suppliers
WHERE (SELECT count(*) FROM Products WHERE SupplierId = Suppliers.supplierId AND Price < 20) > 0;
在这种情况下,如果找到第一个产品,它将产生收益;
SELECT count(SupplierName)
FROM Suppliers
WHERE EXISTS (SELECT * FROM Products WHERE SupplierId = Suppliers.supplierId AND Price < 20);
答案 3 :(得分:0)
在大多数情况下,EXISTS()
更具表现力。例如,尝试将以下片段重编为NOT COUNT(*) > 0
版本。哪一个更具可读性?
--
-- All the possible moves for the current board.
-- ,which is := all the (empty spots * all the numbers 1-9)
-- for which the same number does not occur yet in the same {row/col/box}.
--
CREATE VIEW valid_moves AS (
SELECT DISTINCT su.iii AS iii
, su.yyy AS yyy
, su.xxx AS xxx
, su.box AS box
, su.y3 AS y3
, su.x3 AS x3
, su.z3 AS z3
, nn.val AS val
FROM v_sudoku su -- current board, including filled-in numbers
CROSS JOIN all_numbers nn -- Cartesian product here ...
WHERE su.val IS NULL -- empty spots
AND NOT EXISTS (SELECT * FROM v_sudoku ny
WHERE ny.yyy = su.yyy AND ny.val = nn.val
)
AND NOT EXISTS (SELECT * FROM v_sudoku nx
WHERE nx.xxx = su.xxx AND nx.val = nn.val
)
AND NOT EXISTS (SELECT * FROM v_sudoku nz
WHERE nz.box = su.box AND nz.val = nn.val
)
);