zoukankan      html  css  js  c++  java
  • [sql]高级语法-SELECT专题

    目录:

    1. 用到的表

    2. 原生用法,针对select语句提供的一些功能

    3. 复合使用多种select语法

    一. 表情况


    表1: Persons表

    复制代码
    mysql> select lastname, firstname,  address, age from Persons;
    +----------+-----------+---------+------+
    | lastname | firstname | address | age  |
    +----------+-----------+---------+------+
    | wu       | xiaohong  | L       |   40 |
    | wu       | xiaohong1 | H       | NULL |
    | zhao     | gao       | H       | NULL |
    | sun      | bin       | H       | NULL |
    | li       | bai       | H       | NULL |
    +----------+-----------+---------+------+
    5 rows in set
    复制代码

    表2: Family表,家族表

    复制代码
    mysql> select * from Family;
    +----------+---------+---------+
    | lastname | origin  | history |
    +----------+---------+---------+
    | qian     | xian    |     102 |
    | sun      | NULL    | NULL    |
    | wu       | dongbei |   200.5 |
    | zhao     | xian    |    10.3 |
    +----------+---------+---------+
    4 rows in set
    复制代码

    二. 原生用法


    1. 连接(JOIN)

            当需要从两个表中获取数据的时候,据需要使用join。当然,既然需要从连个表中获取,那么这两个表一般都是有关联的,比如存放一个人的两部分信息等;通常,联系连个表的字段均为两个表的主键(primary key);而所谓join, 翻译过来就是交叉捆绑的意思, 具体若何捆绑又分: 内连接(inner join), 左连接(left join), 右连接(right join), 以及全连接(full join)
    接下里我们就一个个分析来.  

    0) 使用一般的select语句实现获取某个人的基本信息以及对应的家族信息

    复制代码
    mysql>select p.firstname, p.lastname, f.history  
        from Persons as p, Family as f where p.lastname=f.lastname;
    +-----------+----------+---------+
    | firstname | lastname | history |
    +-----------+----------+---------+
    | bin       | sun      | NULL    |
    | xiaohong  | wu       |   200.5 |
    | xiaohong1 | wu       |   200.5 |
    | gao       | zhao     |    10.3 |
    +-----------+----------+---------+
    4 rows in set
    复制代码

    1)内连接(inner join)/连接(join)

    复制代码
    mysql>select p.firstname, p.lastname, f.history  
        from Persons as p 
        INNER JOIN Family as f ON p.lastName = f.lastName
        ORDER BY f.history;
    +-----------+----------+---------+
    | firstname | lastname | history |
    +-----------+----------+---------+
    | bin       | sun      | NULL    |
    | gao       | zhao     |    10.3 |
    | xiaohong  | wu       |   200.5 |
    | xiaohong1 | wu       |   200.5 |
    +-----------+----------+---------+
    4 rows in set
    
    mysql> select p.firstname, p.lastname, f.history  
        from Persons as p 
        CROSS JOIN Family as f ON p.lastName = f.lastName
        ORDER BY f.history;
        
    mysql> select p.firstname, p.lastname, f.history  
        from Persons as p 
        JOIN Family as f ON p.lastName = f.lastName
        ORDER BY f.history;
    复制代码

    解析:Persons INNER JOIN Family  ON p.lastName = f.lastName 完全等同于
         select Persons, Family  where p.lastName = f.lastName
      其核心思想是: 找到 两个集合中重叠的部分,
                    所以对于李白家,由于没有家族信息; 对于钱家族,由于已经没有后代成员信息了,
           因此结果集中因为找不到匹配(.lastname = .lastname)导致不能将所有成员罗列出来
    另外, cross join,返回被连接的两个表的笛卡尔积,返回结果的行数等于两个表行数的乘积, 在有条件(on)的情况下等同inner join,
          join(缺省) 就是 inner join,  在没有条件的情况下由于内部实现的算法不同, 则效率要高于cross join;

    2)左连接(left join)/左外连接(left Outer join)

    复制代码
    mysql> select p.firstname, p.lastname, f.history  
        from Persons as p 
        LEFT JOIN Family as f ON p.lastName = f.lastName;
    +-----------+----------+---------+
    | firstname | lastname | history |
    +-----------+----------+---------+
    | xiaohong  | wu       |   200.5 |
    | xiaohong1 | wu       |   200.5 |
    | gao       | zhao     |    10.3 |
    | bin       | sun      | NULL    |
    | bai       | li       | NULL    |
    +-----------+----------+---------+
    5 rows in set
    复制代码

    解析: 左连接顾明思议, 则是以左侧(第一个)表作为核心,向右侧(第二个)表发起连接

          核心思想: 取两个集合中,第一个集合  + 二者重叠部分;
                 所以对于李白家已经可以占有一席之地了,但是钱家仍然不再列

    3)右连接(right join)/右外连接(right Outer join)

    mysql> select p.firstname, p.lastname, f.history  
        from Persons as p 
        RIGHT JOIN Family as f ON p.lastName = f.lastName;

    核心思想等同左连接,只不过核心表为右侧(第二个)...

    注:此时取值最好要取右表(如select p.firstname, f.lastname,...),否则有可能会出现全空条目

    4)全连接(full join)/(full Outer join)

    mysql> select p.firstname, p.lastname, f.history  
        from Persons as p 
        FULL JOIN Family as f ON p.lastName = f.lastName;
    解析: 首先以第一个表为核心做左连接, 然后将第二个表中剩余部分也append下来, 相当于两个集合的并集;
    注:mysql不支持FULL JOIN, 可以用left join 和 right join的并集 或者直接用笛卡儿积(cross join)
    复制代码
    mysql>select p.firstname, p.lastname, f.history  from Persons as p RIGHT JOIN Family as f ON p.lastName = f.lastName
        union
        select p.firstname, f.lastname, f.history  from Persons as p RIGHT JOIN Family as f ON p.lastName = f.lastName;
    +-----------+----------+---------+
    | firstname | lastname | history |
    +-----------+----------+---------+
    | xiaohong  | wu       |   200.5 |
    | xiaohong1 | wu       |   200.5 |
    | gao       | zhao     |    10.3 |
    | bin       | sun      | NULL    |
    | NULL      | NULL     |     102 |
    | NULL      | qian     |     102 |
    +-----------+----------+---------+
    6 rows in set
    复制代码

    解析:需要注意的是,在做分别的连接时要以取对应的纽带,什么意思?
          就是说我们在做连接的时候,使用的是lastname作为纽带,那么在做连接的时候,左连接使用左集合.lastname, 右连接使用右集合.lastname.

    5)笛卡尔积(cross join)
    在数学中,笛卡尔乘积是指两个集合X和Y的笛卡尓积(Cartesian product),又称直积,表示为X × Y, 即第一个对象是X的成员, 第二个对象是Y的成员的所有可能有序对。
    实际上,其等价于select * from A, B;
    解析:首先以第一个表为核心做左连接, 然后以第二个表为核心做右连接, 相当于两个集合的等价合并;

    小结:
    所谓连接,实际就是做排列组合,整个的核心原理可以如下图所示
    关于"外"连接, 是相对于内连接而言, 所以左连接右连接全连接都可以认为是"外"连接
    可以将连接的范围从小到大排序为: 内连接 < 左连接/右连接  < 全连接  < 交叉连接

    2. 结果限定(limit)

    3.联合(union, union all)

    核心思想: 用于合并两个或多个 SELECT 语句的结果集。
    特点:
    1)要求UNION内部的SELECT语句必须拥有相同数量的列。列也必须拥有相似的数据类型(待确定)。同时,每条SELECT语句中的列的顺序必须相同。
    2)默认地,UNION 操作符选取不同的值。如果允许重复的值,则使用 UNION ALL。
    3)UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。

    例1: UNION的用法

    复制代码
    mysql> select p.lastname, p.firstname, p.address  from Persons as p
        union
        select f.lastname, f.origin, f.history  from Family as f;
    +----------+-----------+---------+
    | lastname | firstname | address |
    +----------+-----------+---------+
    | wu       | xiaohong  | L       |
    | wu       | xiaohong1 | H       |
    | zhao     | gao       | H       |
    | sun      | bin       | H       |
    | li       | bai       | H       |
    | qian     | xian      | 102     |
    | sun      | NULL      | NULL    |
    | wu       | dongbei   | 200     |
    | zhao     | xian      | 10.3    |
    +----------+-----------+---------+
    9 rows in set
    复制代码
    复制代码
    mysql> select p.lastname, p.memebers  from Persons as p
        union
        select f.lastname, f.memebers  from Family as f;
    +----------+----------+
    | lastname | memebers |
    +----------+----------+
    | wu       |        4 |
    | wu       | NULL     |
    | zhao     | NULL     |
    | sun      | NULL     |
    | li       | NULL     |
    | qian     |        2 |
    | zhao     |        1 |
    +----------+----------+
    7 rows in set
    复制代码

    解析: 首先select的结果集的数量必须相同,即都是3个或者2个;
          然后, 另外所谓"相似"类型,则一般指字段必须是有限长度的,比如date,text和float也算, 不同限制的int也算(哪些不算呢?)
          最后,合并后的结果集使用的是第一个select语句中用的列明,
      
    例2: UNION ALL的用法
    复制代码
    mysql> select p.lastname, p.memebers  from Persons as p
        union all
        select f.lastname, f.memebers  from Family as f;
    +----------+----------+
    | lastname | memebers |
    +----------+----------+
    | wu       |        4 |
    | wu       | NULL     |
    | zhao     | NULL     |
    | sun      | NULL     |
    | li       | NULL     |
    | qian     |        2 |
    | sun      | NULL     |
    | wu       |        4 |
    | zhao     |        1 |
    +----------+----------+
    9 rows in set
    复制代码

    解析: 其中wu|4 和sun|NULL 的重复条目也都保留了

     4.结果聚合(Group BY)

     从所给的列明返回分组的查询结果,可用于查询具有相同值的列

     例1: 基础用法

    复制代码
    mysql> select lastname, firstname, count(*) from Persons group by lastname;
    +----------+-----------+----------+
    | lastname | firstname | count(*) |
    +----------+-----------+----------+
    | li       | bai       |        1 |
    | sun      | bin       |        1 |
    | wu       | xiaohong  |        2 |
    | zhao     | gao       |        1 |
    +----------+-----------+----------+
    4 rows in set
    复制代码

    解析: 根据lastename进行分组,于是同姓wu分到一组,且这组里面有2个元素

     例2: 高级用法

    <<待添加>>

    5. 唯一性(distinct)

    二. 复合用法


    1.  将查询结果作为查询条件

    SELECT * FROM udpbind WHERE proxyuuid=(SELECT `uuid` FROM udpbind WHERE 
            proxyuuid='515c524db84e4ce5a57b20e00110161d' AND pctype=1 AND port=5060 LIMIT 1); 解析:从表中取得符合条件的表项的uuid字段作为新的查询条件:最终获取proxyuuid为上次取得的uuid的所有表项 tip1:因为把查询结果作为条件了,所以别忘了用limit保证只获得一个 tip2:因为uuid和proxyuuid都是字符串,所以作为条件的uuid一定记得用``,否则会作为非字符串,于是匹配不到 tip3:之前还想是不是要使用DISTINCT,于是查了一下他的函数, 的意思表示:如果select的列(可多个)组合有重复的,则取一个, 如果: select a,b from.... 结果是:1 1 1 2 1 1 如果:select distinct a, b from xxx 结果是: 1 1 1 2

    2.  待添加1

    3. 待添加2

  • 相关阅读:
    Azure HPC Pack Cluster添加辅助节点
    Azure HPC Pack 辅助节点模板配置
    Azure HPC Pack配置管理系列(PART6)
    Windows HPC Pack 2012 R2配置
    Azure HPC Pack 节点提升成域控制器
    Azure HPC Pack VM 节点创建和配置
    Azure HPC Pack 部署必要条件准备
    Azure HPC Pack 基础拓扑概述
    Azure VM 性能计数器配置
    Maven私仓配置
  • 原文地址:https://www.cnblogs.com/shuiguizi/p/14513293.html
Copyright © 2011-2022 走看看