sql exist的用法

101 阅读4分钟
SELECT column_name(s)
FROM table_name
WHERE EXISTS
(SELECT column_name FROM table_name WHERE condition);

Websites;
+----+--------------+---------------------------+-------+---------+
| id | name         | url                       | alexa | country |
+----+--------------+---------------------------+-------+---------+
| 1  | Google       | https://www.google.cm/    | 1     | USA     |
| 2  | 淘宝       | https://www.taobao.com/   | 13    | CN      |
| 3  | 菜鸟教程 | http://www.runoob.com/    | 4689  | CN      |
| 4  | 微博       | http://weibo.com/         | 20    | CN      |
| 5  | Facebook     | https://www.facebook.com/ | 3     | USA     |
+----+--------------+---------------------------+-------+---------+

access_log;
+-----+---------+-------+------------+
| aid | site_id | count | date       |
+-----+---------+-------+------------+
|   1 |       1 |    45 | 2016-05-10 |
|   2 |       3 |   100 | 2016-05-13 |
|   3 |       1 |   230 | 2016-05-14 |
|   4 |       2 |    10 | 2016-05-14 |
|   5 |       5 |   205 | 2016-05-14 |
|   6 |       4 |    13 | 2016-05-15 |
|   7 |       3 |   220 | 2016-05-15 |
|   8 |       5 |   545 | 2016-05-16 |
|   9 |       3 |   201 | 2016-05-17 |
+-----+---------+-------+------------+
9 rows in set (0.00 sec)

-- 查找总访问量(count 字段)大于 200 的网站是否存在
SELECT Websites.name, Websites.url
FROM Websites
WHERE EXISTS (SELECT count FROM access_log WHERE
              Websites.id = access_log.site_id
              AND count > 200);

-- 查找总访问量(count 字段)小于 200 的网站是否存在
SELECT Websites.name, Websites.url 
FROM Websites 
WHERE NOT EXISTS (SELECT count FROM access_log 
                  WHERE Websites.id = access_log.site_id AND count > 200);  

                  

Websites表中选择nameurl两个字段的值,并且通过EXISTS子查询来筛选出在access_log表中对应的记录中访问次数大于200的网站。

具体来说,子查询中的SELECT count FROM access_log WHERE Websites.id = access_log.site_id AND count > 200语句会返回一个数字,表示访问次数大于200的网站在access_log表中出现的次数。如果这个数字大于0,那么说明存在访问次数大于200的网站,EXISTS子查询返回的结果为真,WHERE子句就会过滤掉这些网站,只返回访问次数不大于200的网站。

最终,查询结果包括Websites.nameWebsites.url两个字段的值,表示访问次数不大于200的网站的名称和URL。

EXISTS子查询可以用来检查一个查询是否返回了至少一行记录,它通常用在WHERE子句中。如果你觉得理解起来比较费劲,可以尝试使用JOIN子句来代替。

例如,假设你想查询在access_log表中访问次数大于200的网站,可以使用以下查询语句:

SELECT Websites.name, Websites.url
FROM Websites
JOIN (
  SELECT site_id, COUNT(*) AS count
  FROM access_log
  GROUP BY site_id
  HAVING COUNT(*) > 200
) AS al ON Websites.id = al.site_id;

这个查询语句中,子查询使用GROUP BY子句和COUNT函数来计算每个网站在access_log表中的访问次数,并且只选择访问次数大于200的记录。然后,外层查询使用JOIN子句将Websites表和子查询的结果连接起来,只选择访问次数大于200的网站。这种方法可能会比EXISTS子查询更容易理解和维护。

UPDATE

在 SQL 中,EXISTS 关键字通常用于在 UPDATE 语句中检查子查询的结果是否存在。下面是一个使用 EXISTS 的双表 UPDATE 示例:

假设我们有两个表,一个是 employees 表,包含员工的基本信息,另一个是 salary_changes 表,包含员工的薪水变化信息。我们想要更新 employees 表中的薪水,根据 salary_changes 表中的薪水变化条件。

-- 创建示例表 employees
CREATE TABLE employees (
    employee_id INT PRIMARY KEY,
    employee_name VARCHAR(50),
    salary INT
);

-- 创建示例表 salary_changes
CREATE TABLE salary_changes (
    employee_id INT,
    salary_change_amount INT
);

-- 插入一些示例数据
INSERT INTO employees VALUES (1, 'Alice', 50000);
INSERT INTO employees VALUES (2, 'Bob', 60000);

INSERT INTO salary_changes VALUES (1, 1000);
INSERT INTO salary_changes VALUES (2, 1500);

现在,我们可以使用 EXISTS 关键字来更新 employees 表中的薪水:

-- 两个表就是这么写的,通过子查询知道自己增减多少钱
UPDATE employees
SET salary = salary + (SELECT salary_change_amount FROM salary_changes WHERE salary_changes.employee_id = employees.employee_id)
WHERE EXISTS (SELECT 1 FROM salary_changes WHERE salary_changes.employee_id = employees.employee_id);

-- 在 EXISTS 子查询中,通常是用来检查子查询是否返回结果,而不涉及到具体的连接条件。
-- 这是因为 EXISTS 关键字只关心子查询是否返回了结果,而不关心结果的具体内容。

UPDATE employees
SET salary = salary + 1000  -- 假设薪水变化是 1000
WHERE EXISTS (SELECT 1 FROM salary_changes WHERE salary_changes.employee_id = employees.employee_id);

这个 UPDATE 语句的作用是,对于 salary_changes 表中存在记录的员工,在 employees 表中将其薪水增加相应的薪水变化值。这里使用了 EXISTS 子查询来检查是否存在符合条件的薪水变化记录。