• [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

  • 相关阅读:
    UVALive 7146 (贪心+少许数据结构基础)2014acm/icpc区域赛上海站
    hdu 1754 I Hate It(树状数组区间求最值)2007省赛集训队练习赛(6)_linle专场
    【进阶——树状数组】 区间求最值
    软件测试作业4
    软件测试作业三 尝试使用JUnit
    软件测试作业2:读代码回答问题
    软件测试作业1:描述一个曾遇到的错误
    hdu1064Financial Management
    hdu1161Eddy's mistakes
    hdu1020Encoding
  • 原文地址:https://www.cnblogs.com/shuiguizi/p/14513293.html
Copyright © 2020-2023  润新知