为什么在SQL中需要“ WHERE EXISTS”运算符?

时间:2018-08-29 17:22:19

标签: sql

我发现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”吗?

4 个答案:

答案 0 :(得分:3)

在您的示例中,EXISTS效率更高。子查询需要读取所有个匹配行以进行计数。

根据合同,

EXISTS可以(并且确实!)停在匹配的第一行。

您可能会说SQL引擎可以识别这种情况。但是,对于更复杂的查询,这将非常非常困难。

与您的观点相反,我发现EXISTSIN或具有聚合功能的相关子查询还要有用。这是表达此逻辑的首选方法。

答案 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
                )
        );