• MySQL分组数据和子查询


    分组数据

    创建分组

    mysql> SELECT vend_id,COUNT(*) AS num_prods
    	   FROM products 
    	   GROUP BY vend_id;
    +---------+-----------+
    | vend_id | num_prods |
    +---------+-----------+
    |    1001 |         3 |
    |    1002 |         2 |
    |    1003 |         7 |
    |    1005 |         2 |
    +---------+-----------+
    4 rows in set (0.01 sec)
    
    • 上面的SELECT语句指定了两个列,vend_id包含产品供应商的ID,
      num_prods为计算字段(用COUNT(*)函数建立)。GROUP BY子句指
      示MySQL按vend_id排序并分组数据。这导致对每个vend_id而不是整个表
      计算num_prods一次。从输出中可以看到,供应商1001有3个产品,供应商
      1002有2个产品,供应商1003有7个产品,而供应商1005有2个产品。
    • 因为使用了GROUP BY,就不必指定要计算和估值的每个组了。系统
      会自动完成。GROUP BY子句指示MySQL分组数据,然后对每个组而不是
      整个结果集进行聚集。
    • 在具体使用GROUP BY子句前,需要知道一些重要的规定。
      • GROUP BY子句可以包含任意数目的列。这使得能对分组进行嵌套,
        为数据分组提供更细致的控制。
      • 如果在GROUP BY子句中嵌套了分组,数据将在最后规定的分组上
        进行汇总。换句话说,在建立分组时,指定的所有列都一起计算
        (所以不能从个别的列取回数据)。
      • GROUP BY子句中列出的每个列都必须是检索列或有效的表达式
        (但不能是聚集函数)。如果在SELECT中使用表达式,则必须在
        GROUP BY子句中指定相同的表达式。不能使用别名。
      • 除聚集计算语句外,SELECT语句中的每个列都必须在GROUP BY子
        句中给出。
      • 如果分组列中具有NULL值,则NULL将作为一个分组返回。如果列
        中有多行NULL值,它们将分为一组。
      • GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。

    过滤分组

    • HAVING非常类似于WHERE。事实上,目前为止所学过的所有类型的WHERE子句都可以用HAVING来替代。唯一的差别是WHERE过滤行,而HAVING过滤分组。
    mysql> SELECT cust_id,COUNT(*) AS orders 
    	   FROM orders 
    	   GROUP BY cust_id 
    	   HAVING COUNT(*)>=2;
    +---------+--------+
    | cust_id | orders |
    +---------+--------+
    |   10001 |      2 |
    +---------+--------+
    1 row in set (0.00 sec)
    
    • HAVING和WHERE的差别 这里有另一种理解方法,WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤。这是一个重要的区别,WHERE排除的行不包括在分组中。这可能会改变计算值,从而影响HAVING子句中基于这些值过滤掉的分组。

    分组和排序

    mysql> SELECT order_num,SUM(quantity*item_price)AS ordertotal 
    	   FROM orderitems
     	   GROUP BY order_num 
     	   HAVING SUM(quantity*item_price)>=50 
     	   ORDER BY ordertotal;
    +-----------+------------+
    | order_num | ordertotal |
    +-----------+------------+
    |     20006 |      55.00 |
    |     20008 |     125.00 |
    |     20005 |     149.87 |
    |     20007 |    1000.00 |
    +-----------+------------+
    4 rows in set (0.01 sec)
    
    • 它检索总计订单价格大于等于50的订单的订单号和总计订单价格,按总计订单价格排序输出。

    SELECT 子句顺序

    字句 说明 是否必须使用
    SELECT 要返回的列或表达式
    FORM 从中检索数据的表 仅在从表选择数据时使用
    WHERE 行级过滤
    GROUP BY 分组说明 仅在按组计算聚集时使用
    HAVING 组级过滤
    ORDER BY 输出排序顺序
    LIMIT 要检索的行数

    子查询

    • 子查询就是把一条SELECT语句返回的结果用于另一条SELECT语句的WHERE子句。

    利用子查询进行过滤

    mysql> SELECT order_num 
    	   FROM orderitems
           WHERE prod_id='TNT2';
    +-----------+
    | order_num |
    +-----------+
    |     20005 |
    |     20007 |
    +-----------+
    2 rows in set (0.01 sec)
    
    mysql> SELECT cust_id 
    	   FROM orders 
    	   where order_num IN(20005,20007);
    +---------+
    | cust_id |
    +---------+
    |   10001 |
    |   10004 |
    +---------+
    2 rows in set (0.00 sec)
    
    mysql> SELECT cust_id
    	   FROM orders 
    	   where order_num IN(SELECT order_num
                              FROM orderitems 
                              WHERE prod_id='TNT2');
    +---------+
    | cust_id |
    +---------+
    |   10001 |
    |   10004 |
    +---------+
    2 rows in set (0.01 sec)
    
    • 在SELECT语句中,子查询总是从内向外处理。在处理上面的SELECT语句时,MySQL实际上执行了两个操作。首先,它执行下面的查询:
    SELECT order_num FROM orderitems WHERE prod_id='TNT2';
    
    • 此查询返回两个订单号:20005和20007。然后,这两个值以IN操作符要求的逗号分隔的格式传递给外部查询的WHERE子句。外部查询变成:
    SELECT cust_id FROM orders where order_num IN(20005,20007);
    
    • 可以看到,输出是正确的并且与前面硬编码WHERE子句所返回的值相同。

    • 列必须匹配 在WHERE子句中使用子查询(如这里所示),应该保证SELECT语句具有与WHERE子句中相同数目的列。通常,子查询将返回单个列并且与单个列匹配,但如果需要也可以使用多个列。

    • 虽然子查询一般与IN操作符结合使用,但也可以用于测试等于(=)、不等于(<>)等。

    作为计算字段使用子查询

    mysql> SELECT COUNT(*) AS orders FROM orders WHERE cust_id=10001;
    +--------+
    | orders |
    +--------+
    |      2 |
    +--------+
    1 row in set (0.00 sec)
    
    • 为了对每个客户执行COUNT()计算,应该将COUNT()作为一个子查询。请看下面的代码:
    mysql> SELECT cust_name,cust_state,(SELECT COUNT(*) 
                                        FROM orders 
                                        WHERE orders.cust_id=customers.cust_id) AS orders 
           FROM customers 
           ORDER BY cust_name;
    +----------------+------------+--------+
    | cust_name      | cust_state | orders |
    +----------------+------------+--------+
    | Coyote Inc.    | MI         |      2 |
    | E Fudd         | IL         |      1 |
    | Mouse House    | OH         |      0 |
    | Wascals        | IN         |      1 |
    | Yosemite Place | AZ         |      1 |
    +----------------+------------+--------+
    5 rows in set (0.01 sec)
    
    • 这 条 SELECT 语句对 customers 表中每个客户返回 3 列 :cust_name、cust_state和orders。orders是一个计算字段,它是由圆括号中的子查询建立的。该子查询对检索出的每个客户执行一次。在此例子中,该子查询执行了5次,因为检索出了5个客户。

    • 子查询中的WHERE子句与前面使用的WHERE子句稍有不同,因为它使用了完全限定列名(在第4章中首次提到)。下面的语句告诉SQL比较orders表中的cust_id与当前正从customers表中检索的cust_id:

      WHERE orders.cust_id=customers.cust_id
      
    • 相关子查询(correlated subquery) 涉及外部查询的子查询。这种类型的子查询称为相关子查询。

  • 相关阅读:
    寒假day08
    操作系统(一)操作系统的目标和作用
    数据结构排序算法稳定性总结——写给自己看
    网络请求生命周期
    PHP 不同类型之间的松散和严格比较
    php配置可被设定范围
    laravel5.7 前后端分离开发 实现基于API请求的token认证
    laravel 自动加载 自定义的文件/辅助函数
    laravel5.7 migrate 时报错 Specified key was too long error 解决方案
    PHP 命名空间
  • 原文地址:https://www.cnblogs.com/chengmf/p/13158293.html
Copyright © 2020-2023  润新知