索引

Understanding Data Grouping

mysql> SELECT COUNT(*) AS num_prods
-> FROM products
-> WHERE vend_id=1003;
+-----------+
| num_prods |
+-----------+
| 7 |
+-----------+
1 row in set (0.00 sec)

我们可以通过改变 WHERE 条件中与 vend_id 判等的值(1003. 1004. 1005 .. .)来获取各个供货商的产品数量,但是没办法一次性把它们罗列出来,GROUP BY 恰好可以解决这个问题:

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.00 sec)

分组允许把数据分为多个逻辑组,以便能对每个组进行聚集计算。

mysql> SELECT vend_id, COUNT(*) AS num_prods
-> FROM products
-> GROUP BY vend_id WITH ROLLUP;
+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
| 1001 | 3 |
| 1002 | 2 |
| 1003 | 7 |
| 1005 | 2 |
| NULL | 14 |
+---------+-----------+
5 rows in set (0.00 sec)

↑ 利用该 关键字可以同时拿到汇总值。

The GROUP BY clause must come after any WHERE clause and before any ORDER BY clause.

Filtering Groups

mysql> SELECT cust_id, COUNT(*) AS orders
-> FROM orders
-> GROUP BY cust_id
-> HAVING COUNT(*) >= ;
+---------+--------+
| cust_id | orders |
+---------+--------+
| 10001 | 2 |
+---------+--------+
1 row in set (0.00 sec)

如果有 WHERE 那必须是在 GROUP BY 的上面。

WHERE filters before data is grouped, and HAVING filters after data is grouped.

Grouping and Sorting

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; # Finally, the output is sorted using the ORDER BY clause.
+-----------+------------+
| order_num | ordertotal |
+-----------+------------+
| 20006 | 55.00 |
| 20008 | 125.00 |
| 20005 | 149.87 |
| 20007 | 1000.00 |
+-----------+------------+
4 rows in set (0.00 sec)

Don't Forget ORDER BY As a rule, anytime you use a GROUP BY clause, you should also specify an ORDER BY clause. That is the only way to ensure that data is sorted properly. Never rely on GROUP BY to sort your data.

总之,最好在用 GROUP BY 的时候顺手给出 ORDER BY , 除非你完全不在意顺序。

多个字段的 GROUP BY 可以参考这篇文章

Understanding Subqueries

设计数据库需要遵循一些范式,而做范式的基本手段就是拆表,因此数据被分散都若干个表中是不可避免的,很多时候,采用子查询会让事情变得更简单。下面是一个简单的例子:

即将用到的几张表 ↓

mysql> SELECT *
-> FROM orders
-> LIMIT 3;
+-----------+---------------------+---------+
| order_num | order_date | cust_id |
+-----------+---------------------+---------+
| | -- :: | |
| | -- :: | |
| | -- :: | |
+-----------+---------------------+---------+

3 rows in set (0.00 sec) mysql> SELECT *
-> FROM orderitems
-> LIMIT 3;
+-----------+------------+---------+----------+------------+
| order_num | order_item | prod_id | quantity | item_price |
+-----------+------------+---------+----------+------------+
| | | ANV01 | | 5.99 |
| | | ANV02 | | 9.99 |
| | | TNT2 | | 10.00 |
+-----------+------------+---------+----------+------------+

3 rows in set (0.00 sec) mysql> SELECT cust_id, cust_name
-> FROM customers
-> LIMIT 3;
+---------+-------------+
| cust_id | cust_name |
+---------+-------------+
| | Coyote Inc. |
| | Mouse House |
| | Wascals |
+---------+-------------+

3 rows in set (0.00 sec)

假设你现在希望得到购买了 TNT2 的顾客的清单,实际上可以分成下面几个查询:

先找出所有 'TNT2' 相关的订单号,然后通过订单号可以找到对应的顾客号,最后通过顾客号再找到顾客信息:

mysql> SELECT order_num
-> FROM orderitems
-> WHERE prod_id = 'TNT2';
+-----------+
| order_num |
+-----------+
| |
| |
+-----------+

2 rows in set (0.00 sec)
mysql> SELECT cust_id
-> FROM orders
-> WHERE order_num IN (,);
+---------+
| cust_id |
+---------+
| |
| |
+---------+

2 rows in set (0.00 sec)

... / 这好几个查询是可以写在一起的:

mysql> SELECT cust_name, cust_contact
-> FROM customers
-> WHERE cust_id IN (SELECT cust_id
-> FROM orders
-> WHERE order_num IN (SELECT order_num
-> FROM orderitems
-> WHERE prod_id = 'TNT2'));
+----------------+--------------+
| cust_name | cust_contact |
+----------------+--------------+
| Coyote Inc. | Y Lee |
| Yosemite Place | Y Sam |
+----------------+--------------+
2 rows in set (0.00 sec)

仅从拿数据的角度分析上面的命令:x. 最终是要拿到 cust_name 和 cust_contact ,所以首先 SELECT cust_name, cust_contact ,从哪里拿呢?FROM customers,约束条件. cust_id 必须在某个集合内,然后 又 回到 x. 重复,一层一层写下去 ...

效率问题:Subqueries and Performance The code shown here works, and it achieves the desired result. However, using subqueries is not always the most efficient way to perform this type of data retrieval, although it might be. More on this is in Chapter 15, "Joining Tables," where you will revisit this same example.

Using Subqueries As Calculated Fields

 相关子查询就像是一个嵌套的 for 循环 ...

SELECT cust_name,
cust_state,
(SELECT COUNT(*)
FROM orders
WHERE orders.cust_id = customers.cust_id) AS orders

FROM customers
ORDER BY cust_name;

使用字段全名是必要的(这可以算是相关子查询的一个特征),否则 mysql 会把 cust_id = cust_id 当成内查询的表字段自己和自己比较。

外查询每找到一条记录就会 执行 一次 子查询,类似于 SELECT x - 2017 ,每找到一条记录都要做一次运算(这里是减2017)。

Build Queries with Subqueries Incrementally Testing and debugging queries with subqueries can be tricky, particularly as these statements grow in complexity. The safest way to build (and test) queries with subqueries is to do so incrementally, in much the same way as MySQL processes them. Build and test the innermost query first. Then build and test the outer query with hard-coded data, and only after you have verified that it is working embed the subquery. Then test it again. And keep repeating these steps as for each additional query. This will take just a little longer to construct your queries, but doing so saves you lots of time later (when you try to figure out why queries are not working) and significantly increases the likelihood of them working the first time.

MySQL Crash Course #06# Chapter 13. 14 GROUP BY. 子查询的更多相关文章

  1. 警惕 MySql 更新 sql 的 WHERE 从句中的 IN() 子查询时出现的性能陷阱

    警惕 MySql 更新 sql 的 WHERE 从句中的 IN() 子查询时出现的性能陷阱 以下文章来源:https://blog.csdn.net/defonds/article/details/4 ...

  2. MySQL Crash Course #07# Chapter 15. 关系数据库. INNER JOIN. VS. nested subquery

    索引 理解相关表. foreign key JOIN 与保持参照完整性 关于JOIN 的一些建议,子查询 VS. 联表查询 我发现MySQL 的官方文档里是有教程的. SQL Tutorial - W ...

  3. 警惕 MySql 更新 sql 的 WHERE 从句中的 IN() 子查询时出现的陷阱

    mer_stage 表有 216423 条记录,DDL: CREATE TABLE `mer_stage` ( `STAGE_ID` int(11) NOT NULL AUTO_INCREMENT, ...

  4. 《mysql必知必会》笔记2(子查询、联接、组合查询、全文本搜索)

    十四:使用子查询 1:子查询是嵌套在其他查询中的查询. 2:需要列出订购TNT2的所有客户信息,需要下面几步: a:从orderitems表中检索出包含物品TNT2的所有订单号: b:根据上一步得出的 ...

  5. Mysql常用sql语句(19)- in / exists 子查询

    测试必备的Mysql常用sql语句系列 https://www.cnblogs.com/poloyy/category/1683347.html 前言 子查询在我们查询方法中是比较常用的,通过子查询可 ...

  6. MySQL Crash Course #04# Chapter 7. 8 AND. OR. IN. NOT. LIKE

    索引 AND. OR 运算顺序 IN Operator VS. OR NOT 在 MySQL 中的表现 LIKE 之注意事项 运用通配符的技巧 Understanding Order of Evalu ...

  7. MySQL Crash Course #15# Chapter 23. Working with Stored Procedures

    以前写过类似的东西,用来自动生成数据. 你可以将 Stored Procedure 理解为可以重复使用的批处理文件. Stored Procedure 非常有用,我们应该尽可能地去使用它. 那么,应用 ...

  8. MySQL Crash Course #11# Chapter 20. Updating and Deleting Data

    INDEX Updating Data The IGNORE Keyword Deleting Data Faster Deletes Guidelines for Updating and Dele ...

  9. MySQL Crash Course #10# Chapter 19. Inserting Data

    INDEX BAD EXAMPLE Improving Overall Performance Inserting Multiple Rows INSTEAD OF Inserting a Singl ...

随机推荐

  1. ABP之项目的搭建

    ABP是一个非常优秀的框架,使用模块化的管理方式,将当前比较优秀的技术集成到了这个框架中,方便开发者快速搭建自己的网站.作为ABP学习的第一篇,先将ABP框架跑起来看看再说. 1.首先需要去官网下载相 ...

  2. BZOJ2200 道路和航线【好题】【dfs】【最短路】【缩点】

    2200: [Usaco2011 Jan]道路和航线 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1384  Solved: 508[Submit] ...

  3. ArcEngine创建要素类_线类型

    public ESRI.ArcGIS.Geodatabase.IFeatureClass CreateFeatureClassForLine(ESRI.ArcGIS.Geodatabase.IWork ...

  4. VS 2005 处理条件

    1. VS 设置断点; 2.VS 查找需要跟踪的内存地址,如果是指针,需要取指针存放地的地址; 3. 4.继续运行,直到内存内容被改写.

  5. JS中生成和解析JSON

    1.JS中生成JSON对象的方法: var json = []; var row1 = {}; row1.id= "1"; row1.name = "jyy"; ...

  6. 2018/04/02 每日一个Linux命令 之 新建/修改/删除群组

    -- 新建群组 groupadd [群组名] -- 修改群组名称 groupmod [群组名] [新群组名] -n 修改组名 -g 修改组识别码 -- 删除群组 groupdel [删除的组名] --

  7. 如果要写php扩展啥的, 要看什么?

    1.写PHP扩展并不难 有一定C语言基础即可.切记一定要在Linux平台下开发,不要用Windows 这里有一篇博文,可以看下http://rango.swoole.com/archives/152 ...

  8. SQL实现交,并,差操作

    有的数据库不支持intersect,except,所以交集,和差集使用嵌套查询来做比较靠谱. a表和b表具有完全一样的结构 mysql> desc a; +-------+----------- ...

  9. 【深入理解javascript】王福朋,厉害了word哥

    学习前端有一段时间了,一直以来也没搞明白js中这个闭包到底是个什么东西,有时候看看别人的博客或者知乎的文章,大概上有个了解,可过一段时间也就忘了.偶然间有幸拜读了博客园-王福朋的这一系列文章<深 ...

  10. 001-GPG入门教程

    对信息加密和解密.需要用到GnuPG软件(简称GPG),它是目前最流行.最好用的加密工具之一. 一.什么是GPG 要了解什么是GPG,就要先了解PGP. 1991年,程序员Phil Zimmerman ...