MySQL 中 SQL 语句使用子查询方式总结

时间:2025-01-05 00:27 分类:其他教程

在 MySQL 数据库中,子查询是一种强大的工具,它允许我们基于一个或多个外部查询的结果来执行进一步的查询操作。本文将为您详细总结 MySQL 中 SQL 语句使用子查询的各种方式,帮助您更好地理解和应用这一高级功能。

一、子查询的分类

1. 非关联子查询

非关联子查询是指子查询语句可以单独执行,不需要引用包含语句中的任何内容。它们通常用于过滤或计算数据,而不依赖于外部查询的结果。

  • 单行单列子查询:返回一个单行单列的表,称为标量子查询。
SELECT account_id, product_cd, cust_id, avail_balance 
FROM account 
WHERE account_id = (SELECT MAX(account_id) FROM account);
  • 多行单列子查询:返回一个多行单列的表,可以使用 IN、NOT IN、ALL、ANY 等运算符。
SELECT emp_id, fname, lname, title 
FROM employee 
WHERE emp_id IN (SELECT superior_emp_id FROM employee);
  • 多列子查询:返回一个多列的表。
SELECT account_id, product_cd, cust_id 
FROM account 
WHERE (open_branch_id, open_emp_id) IN (SELECT b.branch_id, e.emp_id FROM branch b INNER JOIN employee e ON b.branch_id = e.assigned_branch_id WHERE b.name = 'Woburn Branch');

2. 关联子查询

关联子查询依赖包含语句并引用其一列或者多列。它们在执行时会对每一个候选行进行一次查询。

  • 计算每个客户的账户数
SELECT c.cust_id, c.cust_type_cd, c.city 
FROM customer c 
WHERE 2 = (SELECT COUNT(*) FROM account a WHERE a.cust_id = c.cust_id);
  • 检索所有账户总额在5000到10000之间的所有客户
SELECT c.cust_id, c.cust_type_cd, c.city 
FROM customer c 
WHERE (SELECT SUM(a.avail_balance) FROM account a WHERE a.cust_id = c.cust_id) BETWEEN 5000 AND 10000;

此外,还有 EXISTS 和 NOT EXISTS 运算符,它们用于检查子查询能否返回至少一行。

二、子查询的使用

1. 作为数据源

子查询可以作为 FROM 子句中的非关联数据源,用于生成新的数据或过滤现有数据。

  • 查询每个部门的雇员人数
SELECT d.dept_id, d.`NAME`, e_cnt.how_many 
FROM department d 
INNER JOIN (SELECT dept_id, COUNT(*) how_many FROM employee GROUP BY dept_id) e_cnt ON d.dept_id = e_cnt.dept_id;
  • 生成临时表
SELECT SUM(a.avail_balance) cust_balance 
FROM account a 
INNER JOIN product p ON a.product_cd = p.product_cd 
WHERE p.product_type_cd = 'ACCOUNT' 
GROUP BY a.cust_id;

2. 作为过滤条件

子查询可以用作 WHERE 子句中的过滤条件,用于筛选满足特定条件的记录。

  • 查询开户最多的雇员
SELECT open_emp_id, COUNT(*) how_many 
FROM account 
GROUP BY open_emp_id 
HAVING COUNT(*) = (SELECT MAX(emp_cnt.how_many) FROM (SELECT COUNT(*) how_many FROM account GROUP BY open_emp_id) emp_cnt);
  • 根据账户类型、开户雇员及开户行分组
SELECT p.`name` product, b.`name` branch, CONCAT(e.fname,' ',e.lname) name, account_groups.tot_deposits 
FROM (SELECT product_cd, open_branch_id, open_emp_id, SUM(avail_balance) tot_deposits 
FROM account 
GROUP BY product_cd, open_branch_id, open_emp_id) account_groups 
INNER JOIN employee e ON e.emp_id = account_groups.open_emp_id 
INNER JOIN branch b ON b.branch_id = account_groups.open_branch_id 
INNER JOIN product p ON p.product_cd = account_groups.product_cd 
WHERE p.product_type_cd = 'ACCOUNT' 
ORDER BY 1,2;

3. 作为表达式生成器

子查询可以用作 SELECT、ORDER BY、INSERT 等语句中的表达式生成器,用于动态生成查询条件或结果集中的列。

  • 生成新的账户
INSERT INTO `account` (`account_id`, `product_cd`, `cust_id`, `open_date`, `last_activity_date`, `status`, `open_branch_id`, `open_emp_id`, `avail_balance`, `pending_balance`) 
VALUES (NULL, (SELECT product_cd FROM product WHERE name = 'savings account'), (SELECT cust_id FROM customer WHERE fed_id = '555-55-5555'), '2000-01-15', '2005-01-04', 'ACTIVE', (SELECT branch_id FROM branch WHERE name = 'Quincy Branch'), (SELECT emp_id FROM employee WHERE lname = 'Portman' AND fname = 'Frank'), 0, 0);

三、子查询的总结

子查询在 MySQL 中具有广泛的应用,它可以用于生成新的数据、过滤现有数据、作为表达式生成器等。在使用子查询时,需要注意其分类(非关联和关联)、使用方式以及与其他查询的连接方式。

通过合理地使用子查询,我们可以优化查询性能、简化查询逻辑并提高查询的灵活性和可扩展性。希望本文能为您在 MySQL 子查询的使用方面提供有益的参考和帮助。

四、附录

在实际应用中,子查询的使用可能会涉及到更多的细节和技巧。以下是一些补充示例和注意事项:

1. 将查询结果插入到另一张表中

使用 INSERT INTO ... SELECT 语句可以将查询结果插入到另一张表中。这种方式适用于两张表字段完全一致的情况,或者只希望导入指定字段的情况。

2. SELECT INTO 语句

SELECT INTO 语句可以从一个表中选取数据,然后把数据插入另一个表中。这种方式常用于创建表的备份复件或者用于对记录进行存档。

3. 注意事项

在使用子查询时,需要注意以下几点:

  • 确保子查询的引用列与外部查询的列匹配。
  • 避免在子查询中使用复杂的表达式和函数,以免影响查询性能。
  • 在使用关联子查询时,注意避免使用表别名,以免引发语法错误。

希望本文能为您在 MySQL 子查询的使用方面提供有益的参考和帮助。如有任何疑问或需要进一步的解释,请随时提问。

声明:

1、本博客不从事任何主机及服务器租赁业务,不参与任何交易,也绝非中介。博客内容仅记录博主个人感兴趣的服务器测评结果及一些服务器相关的优惠活动,信息均摘自网络或来自服务商主动提供;所以对本博客提及的内容不作直接、间接、法定、约定的保证,博客内容也不具备任何参考价值及引导作用,访问者需自行甄别。

2、访问本博客请务必遵守有关互联网的相关法律、规定与规则;不能利用本博客所提及的内容从事任何违法、违规操作;否则造成的一切后果由访问者自行承担。

3、未成年人及不能独立承担法律责任的个人及群体请勿访问本博客。

4、一旦您访问本博客,即表示您已经知晓并接受了以上声明通告。

本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 0人参与,0条评论
查看更多

Copyright 2005-2024 yuanmayuan.com 源码园 版权所有 备案信息

声明: 本站非腾讯QQ官方网站 所有软件和文章来自互联网 如有异议 请与本站联系 本站为非赢利性网站 不接受任何赞助和广告