MySQL Crash Course #06# Chapter 13. 14 GROUP BY. 子查询

时间:2022-03-12 03:27:08

索引

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 的顾客的清单,实际上可以分成下面几个查询:

MySQL Crash Course #06# Chapter 13. 14 GROUP BY. 子查询

先找出所有 '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. 关于HTML面试题汇总之H5

    一.H5有哪些新特性,移除了哪些元素?如何处理h5新标签的浏览器兼容性问题,如何区分html和html5 1. html5不在是SGL(通用标记语言)的一个子集,而包含了:图像.位置.存储.多任务等功 ...

  2. JavaScript 10分钟入门

    JavaScript 10分钟入门 随着公司内部技术分享(JS进阶)投票的失利,先译一篇不错的JS入门博文,方便不太了解JS的童鞋快速学习和掌握这门神奇的语言. 以下为译文,原文地址:http://w ...

  3. eclipse的一些常见操作

    调整字体大小:Window-Preferences-General-Appearance-Colors and Fonts-Basic-Text Font

  4. SubsetsTotal Accepted:49746Total Submissions:176257My Submissions

    Subsets Total Accepted: 49746 Total Submissions: 176257My Submissions Given a set of distinct intege ...

  5. RBAC角色权限设计

    https://www.cnblogs.com/vinozly/p/4851364.html

  6. EasyUI ComboGrid 笔记(支持分页)

    业务要求: 下拉框做选择时需要展现多个字段供用户参考,由于内容可能会很多,故还需要考虑分页. 解决方案: 由于项目整体已经采用了EasyUI,在浏览了demo以后,初步考虑使用EasyUI的combo ...

  7. HDU 5977 Garden of Eden (树形dp+快速沃尔什变换FWT)

    CGZ大佬提醒我,我要是再不更博客可就连一月一更的频率也没有了... emmm,正好做了一道有点意思的题,就拿出来充数吧=.= 题意 一棵树,有 $ n (n\leq50000) $ 个节点,每个点都 ...

  8. 用原生javascript写出jquery中slideUp和slideDown效果

    设置块级元素的CSS属性overflow为hidden,然后动态改变height即可 var header=document.getElementsByTagName('header')[0]; he ...

  9. 小学四则运算APP 第二次冲刺 第四天

    团队成员:陈淑筠.杨家安.陈曦 团队选题:小学四则运算APP 第二次冲刺阶段时间:11.29~12.09 本次发布的是合并后的选择题功能界面的设置: ChoiceSet.java: package c ...

  10. HTML5 & how to download SVG in js

    HTML5 & how to download SVG in js how to download SVG in js http://dinbror.dk/blog/how-to-downlo ...