# 语法-Exists

EXISTS 运算符为我们提供了一种基于其他数据是否存在(或不存在)来检索数据的简便方法。更具体地说,它是一个逻辑运算符,用于评估子查询的结果,并返回一个布尔值,该值指示是否返回了行。通常情况下,EXISTSSELECT 语句一起使用,用于确定指定条件下是否存在数据。

# 语法解释

exists 包含两个语法

  • EXISTS (subquery)
  • NOT EXISTS (subquery)

# exists 示例

SELECT * FROM table1 
WHERE EXISTS (SELECT * FROM table2 WHERE table1.id = table2.id);

在这个示例中,EXISTS 子查询将检查 table2 中是否存在与 table1 中的 id 相匹配的行。如果存在这样的行,主查询将返回 table1 中的数据。

#IN 的区别

  1. 执行效率和性能
  • EXISTSIN 运算符之间的主要区别在于 EXISTS 仅检查是否存在数据,而 IN 运算符检查数据是否匹配。
  • EXISTS通常用于关联子查询,适用于较大数据集。当外层的主查询记录较少,子查询中的表大且有索引时,使用EXISTS效率较高‌。当子查询返回的数据量较小且主查询中的表较大且有索引时,使用IN效率较高‌
  1. 对NULL值的处理‌:
  • ‌IN‌:不对NULL进行处理,如果子查询返回任何空值,IN会将其视为未知值,并且不会将其作为匹配条件‌
  • ‌EXISTS‌:会对NULL值进行处理,如果子查询返回任何空值,EXISTS会将其视为匹配条件,并继续执行查询‌
  1. 对NULL值的处理‌:
  • ‌IN‌:不对NULL进行处理,如果子查询返回任何空值,IN会将其视为未知值,并且不会将其作为匹配条件‌。 ‌- EXISTS‌:会对NULL值进行处理,如果子查询返回任何空值,EXISTS会将其视为匹配条件,并继续执行查询‌。
  1. 底层原理‌:
  • ‌IN‌:先将子查询的表进行查询,然后将内表和外表做一个笛卡尔积,再按照条件进行筛选‌
  • ‌EXISTS‌:以外层表为驱动表,逐条查询外表,每次查询都会查看EXISTS的条件语句。如果条件语句能返回记录行,则当前记录被放入结果集;否则被丢弃‌

示例对比

-- EXISTS
SELECT * FROM table1 
WHERE EXISTS (SELECT * FROM table2 WHERE table1.id = table2.id);

-- IN
SELECT * FROM table1 
WHERE table1.id IN (SELECT id FROM table2);

#JOIN 的区别

EXISTSJOIN 运算符之间的主要区别在于 EXISTS 运算符在子查询中找到匹配项后立即返回结果,而 JOIN 运算符会返回所有匹配项,然后过滤掉不需要的行。因此,EXISTS 通常比 JOIN 更高效,尤其是在处理大型数据集时。

示例对比

-- EXISTS
SELECT * FROM table1 
WHERE EXISTS (SELECT * FROM table2 WHERE table1.id = table2.id);

-- JOIN
SELECT * FROM table1 
JOIN table2 ON table1.id = table2.id;

# 场景场景的使用

exists常见的使用场景:

  1. 查询a表在b表中存在数据
  2. 查询a表在b表中不存在数据
  3. 查询时间最新记录

# 查询a表在b表中存在数据

SELECT * FROM table1 
WHERE EXISTS (SELECT * FROM table2 WHERE table1.id = table2.id);

# 查询a表在b表中不存在数据

SELECT * FROM table1 
WHERE NOT EXISTS (SELECT * FROM table2 WHERE table1.id = table2.id);

# 查询时间最新记录

SELECT * FROM table1
WHERE EXISTS (SELECT * FROM table2 WHERE table1.id = table2.id AND table1.time = table2.time);