1.子查询

前面的系列介绍的都是简单的查询场景,其中都只涉及到单张表的数据检索。但是在日常是实际应用中,数据模型之间的关系都非常的复杂,数据的需求一般都是来源于多个数据模型之间的组合而成,即对应多张表的数据关联。

对应以上场景,在SQL中一般有三种实现的方式:

  • 使用多个单条SQL,按逻辑步骤检索,将其中的一条检索结果作为下一条检索的条件;
  • 使用子查询,即将多个单挑SQL利用相应的逻辑关键字合并,子查询是DBMS所支持;
  • 使用表联结的方式,即join;

本章就简单的回顾下SQL中的子查询,从上面的总结中可以看出,子查询其实利用模型之间的关系将单条SQL合并成一条复杂的SQL。那么如果要写出这样的复杂子查询的SQL,首先需要梳理清楚需求中的数据模型之间的关系,根据需求的结果区分出查询主体,查询的关联关系体,然后再分成单步骤的SQL,最后将其合并即可;

下面看个例子:

有三个实体,对应三张表:

  • 顾客表
  • 商品表
  • 订单表

订单中含有商品id,顾客id。现在需求:查询购买商品x1的所有顾客。

  1. 分析:最终的结果是要查询出顾客,所以查询柱体是顾客,即外查询是顾客。但是查询顾客的条件是,购买了x1商品的顾客,所以需要查出购买了x1商品的顾客id,然后根据顾客id查询顾客,所以子查询是根据商品id x1查询。

  2. 步骤:

  • 在表orders中查询x1商品的顾客id: select cus_id from orders where mer_id = 'x1';

  • 根据上述的查询结果作为条件,查询顾客:select * from customers where cus_id = 'xxxx';

最后将根据需求结果和实体的关联关系合并SQL:

select * from customers where customers.cus_id in (select cus_id from orders where mer_id = 'x1');

其实SQL中子查询有两种应用方式:

  • 第一种也就上面的最常使用到的场景,将子查询的结果作为外查询的条件,即子查询属于外查询where子句的一部分
  • 第二种常用是将子查询统计结果作为外查询的列

比如需求:统计每个顾客购订单数量。

  1. 分析:顾客仍然是主体,所以外查询是查顾客表。但是执行的逻辑刚好和上述例子相反,上述是以商品id为条件查询顾客。这里是查询顾客以及其订单数,但是订单数的统计是从顾客这一维度出发,所以需要根据顾客查询订单数。

  2. 步骤:

  • 先查询出所有顾客: select * from customers;
  • 再根据顾客去统计每个顾客的订单数: select count(*) from orders where orders.cus_id = 'xxxxx';

最后组合SQL:

select cus_id, cus_name, (select count(*) from orders where orders.cus_id = customers.cus_id) from customers;

以上例子是子查询的第二种用法。

2.总结

上述总结的子查询的两种方式:

  • 要么是根据子查询的逻辑结果作为外查询的查询条件(子查询在where子句中)
  • 要么是根据外查询的结果作为子查询的条件(子查询在select子句中)

SQL中没有限制子查询的数量,但是一般实际应用中子查询的不宜使用过多:

  • 使用子查询必然会导致SQL更为复杂,SQL表述的语义较为难以理解,可阅读性变差
  • 子查询使用过多,会严重消耗性能
  • 子查询不利于SQL的调试,问题的排查

SQL系列(九)—— 子查询(subQuery)的更多相关文章

  1. 【SqlServer系列】子查询

    1   概述 1.1  已发布[SqlServer系列]文章 [SqlServer系列]SQLSERVER安装教程 [SqlServer系列]数据库三大范式 [SqlServer系列]表单查询 [Sq ...

  2. Sql Server系列:子查询

    1 子查询概念 子查询是嵌套在另一个查询中的普通T-SQL查询.在有一个SELECT语句通过使用小括号创建子查询,作为另一个查询的部分数据或条件的基础. 子查询通常用于满足以下某个需求: ◊ 将一个查 ...

  3. SQL语句:子查询

    一,子查询定义: 子查询就是嵌套在主查询中的查询. 子查询可以嵌套在主查询中所有位置,包括SELECT.FROM.WHERE.GROUP BY.HAVING.ORDER BY. 但并不是每个位置嵌套子 ...

  4. MySQL子查询subquery

    子查询(Subquery)是指出现在其他SQL语句内的SELECT子句. 例如: select * from t1 where col1=(select col2 from t2); 其中select ...

  5. SQL Server 数据库子查询基本语法

    一.SQL子查询语句 1.单行子查询        select ename,deptno,sal        from emp        where deptno=(select deptno ...

  6. sql之独立子查询和相关子查询总结

    1.独立子查询:顾名思义:就是子查询和外层查询不存在任何联系,是独立于外层查询的: 下面就看一个例子: 有一张订单表 Sales.Order 和一张 客户表 Sales.Customer 下面的sql ...

  7. SQL Server 之 子查询与嵌套查询

    当由where子句指定的搜索条件指向另一张表时,就需要使用子查询或嵌套查询. 1 子查询 子查询是一个嵌套在select.insert.update或delete语句或其他子查询中的查询.任何允许使用 ...

  8. 工作中遇到的比较奇怪的一些sql(一些子查询)

    在列中进行子查询 1.在一个表中有多个员工ID,比如一个下单员工,一个修改订单的员工,可以使用在列中进行子查询,具体如下: ( SELECT staff_name FROM sp_staff_basi ...

  9. 优化系列 | DELETE子查询改写优化

    0.导读 有个采用子查询的DELETE执行得非常慢,改写成SELECT后执行却很快,最后把这个子查询DELETE改写成JOIN优化过程 1.问题描述 朋友遇到一个怪事,一个用子查询的DELETE,执行 ...

  10. SQL优化-标量子查询(数据仓库设计的隐患-标量子查询)

    项目数据库集群出现了大规模节点宕机问题.经查询,问题在于几张表被锁.主要问题在于近期得几个项目在数据库SQL编写时大量使用了标量子查询. 为确定为题确实是由于数据表访问量超过单节点限制,做了一些测试. ...

随机推荐

  1. MYSQL的修改表结构SQL语句

    更多java学习资料>>> 1.背景 使用sql语句对表结构进行修改 2.案例演示 案例:表结构 CREATE TABLE `login_user` ( `id` ) NOT NUL ...

  2. office viso 2007根据现有数据库建立数据库模型图

    当数据库表很多的时候,表之间的关系就变得很复杂.光凭记忆很难记住,尤其是数据库键值没有外键约束时. 所以有个数据库模型图各个表之间的关系就显而易见了. 打开 office viso 2007 文件&g ...

  3. nginx日志分割及备份

    环境:centos7 nginx1.16.1 一.分割及备份的目的 nginx默认将日志信息写在一个文件中,时间一久日志文件中条目越来越多,文件越来越大,不方便查看,备份的时候也不需要备份重复的信息, ...

  4. 安装Ubuntu后需要做的事

    卸载软件 纸牌 麻将 扫雷 数独 火狐 邮件 扫描 拍照 照片 视频 计划 日历 打印 备份 计算器 亚马逊 电源统计 音乐播放 远程桌面 To Do LibreOffice 换下载源 装机的时候下载 ...

  5. rhel7学习第四天

    学习<Linux就该这么学>第二周,学习了最重要的几个文件操作命令

  6. 07-numpy-笔记-join

    字符串.join(字符串序列) 一目了然: #!/usr/bin/python # -*- coding: UTF-8 -*- str = "-"; seq = ("a& ...

  7. Pandas | 27 注意事项&窍门

    警告和疑难意味着一个看不见的问题.在使用Pandas过程中,需要特别注意的地方. 与Pandas一起使用If/Truth语句 当尝试将某些东西转换成布尔值时,Pandas遵循了一个错误的惯例. 这种情 ...

  8. 关于时间排序在ios中失效的处理方法

    上个月公司做项目的时候在列表排序的时候产品加了一个需求,通过点击量,发布时间,评论量进行筛选的一个需求. 一开始在电脑上测试基本没问题,然后我也就放下了这个按耐不住的小心脏,然后在完成所有模块后 sh ...

  9. postman使用--Monitor

    前戏 现在我们已经能完成接口的批量执行,添加断言,数据驱动,设置变量等等方法.但是有一天,用户反应说我们的网站访问不了了.这时候,那帮程序猿查日志的查日志,看数据库的看数据库,找到原因在发布到线上已经 ...

  10. C语言之symlink

    函数原型: #include <unistd.h> int symlink(const char * oldpath, const char * newpath); 函数说明: symli ...