何时在SQL中使用NOT EXISTS?

时间:2013-10-02 13:58:00

标签: mysql sql

据我所知,当子查询包含至少一行时,EXISTS返回true,而如果子查询没有返回任何内容,则NOT EXIST返回true。所以对于给定的子查询,两者中的任何一个都应该返回true,对吧? 例如: 1)这将返回一个或多个城市中存在哪种商店?

SELECT DISTINCT store_type FROM stores
WHERE EXISTS 
             (SELECT * 
              FROM cities_stores
              WHERE cities_stores.store_type = stores.store_type);

2)这会回归到哪个商店没有城市?

SELECT DISTINCT store_type FROM stores
WHERE NOT EXISTS 
             (SELECT * 
              FROM cities_stores
              WHERE cities_stores.store_type = stores.store_type);

那么同一个子查询如何为这两个查询提供输出?一个使用EXIST而另一个使用NOT EXIST?

我从中得到了例子 http://dev.mysql.com/doc/refman/5.1/en/exists-and-not-exists-subqueries.html

另外,2 NOT NOT EXISTS如何帮助?这不是一种OR吗? 3)这会返回所有城市中存在哪种商店?

SELECT DISTINCT store_type FROM stores s1
WHERE NOT EXISTS (
            SELECT * FROM cities 
            WHERE NOT EXISTS (
                         SELECT * FROM cities_stores
                         WHERE cities_stores.city = cities.city
                         AND cities_stores.store_type = stores.store_type));

4 个答案:

答案 0 :(得分:3)

EXISTS()子句的典型用法是检查相关表中给定行存在的相关行的位置:

CREATE TABLE clients
        ( client_id INTEGER NOT NULL PRIMARY KEY
        , client_name varchar
        );
CREATE TABLE products
        ( product_id INTEGER NOT NULL PRIMARY KEY
        , product_name varchar
        );
CREATE TABLE orders
        ( client_id INTEGER NOT NULL REFERENCES clients(client_id)
        , product_id INTEGER NOT NULL REFERENCES products(product_id)
        , quantity INTEGER NOT NULL DEFAULT 1
        , order_date DATE
        , PRIMARY KEY (client_id,product_id)
        );
INSERT INTO clients(client_id, client_name) VALUES (1, 'Alice' ), (2, 'Bob' ), (3, 'Charly' ), (4, 'Diana' );
INSERT INTO products(product_id, product_name) VALUES (1, 'Apple' ), (2, 'Banana' ), (3, 'Citrus' );
INSERT INTO orders(client_id,product_id,order_date) VALUES (1,2, '2013-9-8'),(2,1, '2013-9-11'),(3,2, '2013-10-1');

-- Find clients who ordered something
SELECT * FROM clients cl
WHERE EXISTS (
        SELECT * FROM orders oo
        WHERE oo.client_id = cl.client_id
        )
        ;

-- Find clients who never ordered anything
SELECT * FROM clients cl
WHERE NOT EXISTS (
        SELECT * FROM orders oo
        WHERE oo.client_id = cl.client_id
        )
        ;

-- Find products that were never ordered
SELECT * FROM products pr
WHERE NOT EXISTS (
        SELECT * FROM orders oo
        WHERE oo.product_id = pr.product_id
        )
        ;

答案 1 :(得分:2)

为了增加这一点,在使用NOT EXISTS时,通过确保以不会否定索引的方式检查列来帮助提高性能。我认为这适用于较大的数据集,但仍然很有用。 Jayachandran在这里解释得非常好:http://social.msdn.microsoft.com/Forums/sqlserver/en-US/582544fb-beda-46c0-befd-4b28b5c2cdee/select-not-exists-very-slow

答案 2 :(得分:1)

Where not exists非常有用的一个例子是插入时。如果您希望根据某些条件阻止添加重复行,则使用此功能会很有帮助。

例如,在创建参考数据表时,我也会关闭IDENTITY_INSERT以保持数据库之间的ID一致。插入新的参考数据时,我这样做:

INSERT INTO ref_table
(ID, ReferenceData)
SELECT 425, 'foo' where not exists (select 1 from ref_table where ID = 425) UNION ALL
SELECT 426, 'bar' where not exists (select 1 from ref_table where ID = 426) UNION ALL
...
SELECT 532, 'biz' where not exists (select 1 from ref_table where ID = 532)

当然我总是确保我的插入内容是一致的,但我添加了这个条款以便安全测量。

答案 3 :(得分:0)

首先,您需要在内部查询(连接)中具有匹配项的商店类型,在第二种情况下,您希望商店类型与内部查询不匹配!!!

当使用EXISTS / NOT EXISTS子句时,您总是加入内部和外部查询,然后您只需选择是否希望结果匹配或没有匹配。