📜  MySQL子查询

📅  最后修改于: 2020-11-19 00:46:18             🧑  作者: Mango

MySQL子查询

MySQL中的子查询是一个查询,它嵌套在另一个SQL查询中,并与各种运算符一起嵌入SELECT,INSERT,UPDATE或DELETE语句。我们还可以将子查询与另一个子查询嵌套在一起。子查询称为内部查询,而包含子查询的查询称为外部查询。首先执行内部查询,将结果提供给外部查询,然后执行主/外部查询。 MySQL允许我们在任何地方使用子查询,但是必须在括号内将其关闭。 MySQL也将支持SQL标准支持的所有子查询形式和操作。

以下是使用子查询的规则:

  • 子查询应始终用括号括起来。
  • 如果主查询没有用于子查询的多个列,则子查询在SELECT命令中只能有一个列。
  • 我们可以使用各种运算符与子查询,如>,<,=,IN,任何,一些和ALL。当子查询返回多个行时,多行运算符非常有用。
  • 尽管可以在主查询中使用ORDER BY子句,但不能在子查询中使用它。
  • 如果我们在集合函数使用子查询,则它不能立即包含在集合函数。

以下是使用子查询的优点:

  • 子查询以结构化形式进行查询,使我们能够隔离语句的每个部分。
  • 子查询提供了查询表中数据的替代方法。否则,我们需要使用复杂的联接和联合。
  • 子查询比复杂的join或union语句更具可读性。

MySQL子查询语法

以下是在MySQL中使用子查询的基本语法:

SELECT column_list (s) FROM  table_name
WHERE  column_name OPERATOR
   (SELECT column_list (s)  FROM table_name [WHERE])

MySQL子查询示例

让我们借助示例了解它。假设我们有一个名为“ employees”的表,其中包含以下数据:

表:员工

以下是一个简单的SQL语句,该语句返回其ID在子查询中匹配的员工详细信息:

SELECT emp_name, city, income FROM employees 
   WHERE emp_id IN (SELECT emp_id FROM employees);

该查询将返回以下输出:

具有比较运算符的MySQL子查询

运算符是用于对值进行比较,并返回结果,无论是真或假的运算符。下面的比较运算符在MySQL使用<,>,=,<>,<=>,等,我们可以之前或运算符返回单值后使用子查询。返回的值可以是算术表达式或列函数。在此之后,SQL与所述比较运算符者的另一侧上的值的子查询的结果进行比较。以下示例对其进行了更清晰的说明:

以下是一个简单的SQL语句,该语句在子查询的帮助下返回收入超过350000的员工明细:

SELECT * FROM employees 
   WHERE emp_id IN (SELECT emp_id FROM employees 
         WHERE income > 350000);

此查询首先执行子查询,该子查询返回收入> 350000的雇员ID。其次,主查询将返回雇员其雇员ID在子查询返回的结果集中的所有详细信息。

执行该语句后,我们将获得以下输出,在这里我们可以看到收入> 350000的员工明细。

让我们来看看另一个比较运算符,如等式(=)的例子找到使用子查询与最高收入员工的详细信息。

SELECT emp_name, city, income FROM employees 
   WHERE income = (SELECT MAX(income) FROM employees);

它将提供输出,在这里我们可以看到两名收入最高的员工详细信息。

使用IN或NOT-IN运算符的MySQL子查询

如果子查询产生多个值,则需要对WHERE子句使用IN或NOT IN运算符。假设我们有一个名为“ Student”和“ Student2”的表,其中包含以下数据:

表:学生

表:Student2

以下带有NOT IN运算符的子查询从两个表中返回不属于洛杉矶市的学生详细信息,如下所示:

SELECT Name, City FROM student
WHERE City NOT IN (
SELECT City FROM student2 WHERE City='Los Angeles');

执行后,我们可以看到结果包含不属于洛杉矶市的学生详细信息。

FROM子句中的MySQL子查询

如果我们在FROM子句中使用子查询,则MySQL将从子查询返回的输出用作临时表。我们将此表称为派生表,内联视图或实例化子查询。

以下子查询返回订单表中的最大,最小和平均项目数:

SELECT Max(items), MIN(items), FLOOR(AVG(items))
FROM
    (SELECT order_id, COUNT(order_id) AS items FROM orders
    GROUP BY order_date) AS Student_order_detail;

它将给出如下输出:

MySQL相关子查询

MySQL中的相关子查询是依赖于外部查询的子查询。它使用外部查询中的数据或包含对父查询的引用,该父查询也出现在外部查询中。 MySQL从外部查询的每一行对其进行一次评估。

SELECT emp_name, city, income
FROM employees emp WHERE income > ( 
SELECT AVG(income) FROM employees WHERE city = emp.city);

在上面的查询中,我们选择一个雇员名称和城市,其收入高于每个城市中所有雇员的平均收入。

子查询针对指定表的每个城市执行,因为它将针对每一行进行更改。因此,平均收入也会改变。然后,主查询过滤收入高于子查询平均收入的员工明细。

具有EXISTS或NOT EXISTS的MySQL子查询

EXISTS运算符是一个布尔运算符,它返回true或false。它与子查询一起使用,并检查子查询中数据的存在。如果子查询完全返回任何记录,则此运算符返回true。否则,它将返回false。用于否定的NOT EXISTS运算符在子查询不返回任何行时给出真值。否则,它返回false。 EXISTS和NOT EXISTS都与关联子查询一起使用。以下示例更清楚地说明了这一点。假设我们有一个表customer和order,其中包含如下数据:

下面的SQL语句使用EXISTS运算符查找已下订单的客户的姓名,职业和年龄。

SELECT name, occupation, age FROM customer C
WHERE EXISTS (SELECT * FROM Orders O
WHERE C.cust_id = O.cust_id);  

该语句使用NOT EXISTS运算符,该运算符返回未下订单的客户详细信息。

SELECT name, occupation, age FROM customer C
WHERE NOT EXISTS (SELECT * FROM Orders O
WHERE C.cust_id = O.cust_id);  

我们可以看到以下输出以了解上述查询结果。

要阅读有关EXISTS运算符的更多信息,请单击此处。

MySQL ROW子查询

它是一个子查询,返回单行,我们可以在其中获得多个列值。我们可以使用以下运算符比较行子查询=,>,<,> =,<=,<>,!=,<=>。让我们看下面的例子:

SELECT * FROM customer C WHERE ROW(cust_id, occupation) = (
SELECT order_id, order_date FROM Orders O WHERE C.cust_id = O.cust_id);

如果给定的行具有cust_id,职业值等于第一张表中任何行的order_id,order_date值,则WHERE表达式为TRUE,并且每个查询都返回这些第一张表行。否则,表达式为FALSE,查询将生成一个空集,如下图所示:

具有ALL,ANY和SOME的MySQL子查询

,比较运算符之后的任何或SOME我们可以用它后跟关键字ALL的子查询。以下是将子查询与ALL,ANY或SOME一起使用的语法:

operand comparison_operator ANY (subquery)
operand comparison_operator ALL (subquery)
operand comparison_operator SOME (subquery)

ALL关键字将值与子查询返回的值进行比较。因此,如果子查询返回的所有值的比较结果为TRUE,则返回TRUE。如果子查询返回的任何值的比较为TRUE,则ANY关键字将返回TRUE。 ANY和SOME关键字是相同的,因为它们是彼此的别名。以下示例对其进行了更清晰的说明:

SELECT cust_id, name FROM customer WHERE 
cust_id > ANY (SELECT cust_id FROM Orders);

我们将获得如下输出:

如果我们使用ALL代替ANY,则当子查询返回的列中的ALL值的比较为TRUE时,它将返回TRUE。例如:

SELECT cust_id, name FROM customer WHERE 
cust_id > ALL (SELECT cust_id FROM Orders);

我们可以看到如下输出: