第五章 子查询与连接

一、子查询

1.子查询的定义

子查询(Subquery)是指出现在其他SQL语句内的SELECT子句。
例:

SELECT * FROM t1 WHERE col1 = (SELECT col2 FROM t2);

其中SELECT * FROM t1,称为Outer Query/Outer Statement
SELECT col2 FROM t2,称为SubQuery

  • 子查询指嵌套在查询内部,且必须始终出现在圆括号内。
  • 子查询可以包含多个关键词或条件
    • DISTINCT,GROUP BY,ORDER BY,LIMIT,函数等。
  • 子查询的外层查询可以是:SELECT,INSERT,UPDATE,SETDO

2.子查询的返回值

子查询可以返回标量、一行、一列或子查询。

3.使用比较运算符的子查询

使用比较运算符的子查询
=,>,<,>=,<=,<>,!=,<=>
语法结构

operand comparison_operator subquery

example:

SELECT AVG(goods_price) FROM tdb_goods;
/*Result
+------------------+
| AVG(goods_price) |
+------------------+
|     5636.3636364 |
+------------------+
*/
SELECT ROUND(AVG(goods_price), 2) FROM tdb_goods;
/*Result
+----------------------------+
| ROUND(AVG(goods_price), 2) |
+----------------------------+
|                    5636.36 |
+----------------------------+
*/
SELECT goods_id, goods_name, goods_price FROM tdb_goods
WHERE goods_price >= 5636.36;
/*Result
+----------+----------------------------------+-------------+
| goods_id | goods_name                       | goods_price |
+----------+----------------------------------+-------------+
|        3 | G150TH 15.6英寸游戏本            |    8499.000 |
|        7 | SVP13226SCB 13.3英寸触控超极本   |    7999.000 |
|       13 | iMac ME086CH/A 21.5英寸一体电脑  |    9188.000 |
|       17 | Mac Pro MD878CH/A 专业级台式电脑 |   28888.000 |
|       18 |  HMZ-T3W 头戴显示设备            |    6999.000 |
|       20 | X3250 M4机架式服务器 2583i14     |    6888.000 |
|       21 |  HMZ-T3W 头戴显示设备            |    6999.000 |
+----------+----------------------------------+-------------+
*/
SELECT goods_id, goods_name, goods_price FROM tdb_goods
WHERE goods_price >= (SELECT ROUND(AVG(goods_price), 2) FROM tdb_goods);
/*Result
+----------+----------------------------------+-------------+
| goods_id | goods_name                       | goods_price |
+----------+----------------------------------+-------------+
|        3 | G150TH 15.6英寸游戏本            |    8499.000 |
|        7 | SVP13226SCB 13.3英寸触控超极本   |    7999.000 |
|       13 | iMac ME086CH/A 21.5英寸一体电脑  |    9188.000 |
|       17 | Mac Pro MD878CH/A 专业级台式电脑 |   28888.000 |
|       18 |  HMZ-T3W 头戴显示设备            |    6999.000 |
|       20 | X3250 M4机架式服务器 2583i14     |    6888.000 |
|       21 |  HMZ-T3W 头戴显示设备            |    6999.000 |
+----------+----------------------------------+-------------+
*/
SELECT goods_name, goods_price FROM tdb_goods
WHERE goods_cate = '超级本';
/*Result
+---------------------------------+-------------+
| goods_name                      | goods_price |
+---------------------------------+-------------+
| X240(20ALA0EYCD) 12.5英寸超极本 |    4999.000 |
| U330P 13.3英寸超极本            |    4299.000 |
| SVP13226SCB 13.3英寸触控超极本  |    7999.000 |
+---------------------------------+-------------+
*/

4.用ANY,SOME或ALL修饰的比较运算符

operand comparison_operator ANY(subquery)
operand comparison_operator SOME(subquery)    --和ANY等价
operand comparison_operator ALL(subquery)

5.ANY,SOME,ALL关键字

运算符 ANY SOME ALL
>,>= 最小值 最小值 最大值
<,<= 最大值 最大值 最小值
= 任意值 任意值
<>,!= 任意值

example:

SELECT goods_id, goods_name, goods_price FROM tdb_goods
WHERE goods_price > ANY(SELECT goods_price FROM tdb_goods WHERE goods_cate = '超级本');
/*Result
+----------+----------------------------------+-------------+
| goods_id | goods_name                       | goods_price |
+----------+----------------------------------+-------------+
|        2 | Y400N 14.0英寸笔记本电脑         |    4899.000 |
|        3 | G150TH 15.6英寸游戏本            |    8499.000 |
|        5 | X240(20ALA0EYCD) 12.5英寸超极本  |    4999.000 |
|        7 | SVP13226SCB 13.3英寸触控超极本   |    7999.000 |
|       13 | iMac ME086CH/A 21.5英寸一体电脑  |    9188.000 |
|       16 | PowerEdge T110 II服务器          |    5388.000 |
|       17 | Mac Pro MD878CH/A 专业级台式电脑 |   28888.000 |
|       18 |  HMZ-T3W 头戴显示设备            |    6999.000 |
|       20 | X3250 M4机架式服务器 2583i14     |    6888.000 |
|       21 |  HMZ-T3W 头戴显示设备            |    6999.000 |
+----------+----------------------------------+-------------+
*/
SELECT goods_id, goods_name, goods_price FROM tdb_goods
WHERE goods_price > ALL(SELECT goods_price FROM tdb_goods WHERE goods_cate = '超级本');
/*Result
+----------+----------------------------------+-------------+
| goods_id | goods_name                       | goods_price |
+----------+----------------------------------+-------------+
|        3 | G150TH 15.6英寸游戏本            |    8499.000 |
|       13 | iMac ME086CH/A 21.5英寸一体电脑  |    9188.000 |
|       17 | Mac Pro MD878CH/A 专业级台式电脑 |   28888.000 |
+----------+----------------------------------+-------------+
*/
SELECT goods_id, goods_name, goods_price FROM tdb_goods
WHERE goods_price = ANY(SELECT goods_price FROM tdb_goods WHERE goods_cate = '超级本');
/*Result
+----------+---------------------------------+-------------+
| goods_id | goods_name                      | goods_price |
+----------+---------------------------------+-------------+
|        5 | X240(20ALA0EYCD) 12.5英寸超极本 |    4999.000 |
|        6 | U330P 13.3英寸超极本            |    4299.000 |
|        7 | SVP13226SCB 13.3英寸触控超极本  |    7999.000 |
+----------+---------------------------------+-------------+
*/

6.使用[NOT] IN的子查询

语法结构

operand comparison_operator [NOT] IN(subquery)

= ANY与运算符IN等效
!=ALL<>ALL运算符与NOT IN等效。

example:

SELECT goods_id, goods_name, goods_price FROM tdb_goods
WHERE goods_price NOT IN(SELECT goods_price FROM tdb_goods WHERE goods_cate = '超级本');
/*Result
+----------+------------------------------------------------------------------------+-------------+
| goods_id | goods_name                                                             | goods_price |
+----------+------------------------------------------------------------------------+-------------+
|        1 | R510VC 15.6英寸笔记本                                                  |    3399.000 |
|        2 | Y400N 14.0英寸笔记本电脑                                               |    4899.000 |
|        3 | G150TH 15.6英寸游戏本                                                  |    8499.000 |
|        4 | X550CC 15.6英寸笔记本                                                  |    2799.000 |
|        5 | X240(20ALA0EYCD) 12.5英寸超极本                                        |    4999.000 |
|        6 | U330P 13.3英寸超极本                                                   |    4299.000 |
|        7 | SVP13226SCB 13.3英寸触控超极本                                         |    7999.000 |
|        8 | iPad mini MD531CH/A 7.9英寸平板电脑                                    |    1998.000 |
|        9 | iPad Air MD788CH/A 9.7英寸平板电脑 (16G WiFi版)                      |    3388.000 |
|       10 |  iPad mini ME279CH/A 配备 Retina 显示屏 7.9英寸平板电脑 (16G WiFi版) |    2788.000 |
|       11 | IdeaCentre C340 20英寸一体电脑                                         |    3499.000 |
|       12 | Vostro 3800-R1206 台式电脑                                             |    2899.000 |
|       13 | iMac ME086CH/A 21.5英寸一体电脑                                        |    9188.000 |
|       14 | AT7-7414LP 台式电脑 (i5-3450四核 4G 500G 2G独显 DVD 键鼠 Linux )     |    3699.000 |
|       15 | Z220SFF F4F06PA工作站                                                  |    4288.000 |
|       16 | PowerEdge T110 II服务器                                                |    5388.000 |
|       17 | Mac Pro MD878CH/A 专业级台式电脑                                       |   28888.000 |
|       18 |  HMZ-T3W 头戴显示设备                                                  |    6999.000 |
|       19 | 商务双肩背包                                                           |      99.000 |
|       20 | X3250 M4机架式服务器 2583i14                                           |    6888.000 |
|       21 |  HMZ-T3W 头戴显示设备                                                  |    6999.000 |
|       22 | 商务双肩背包                                                           |      99.000 |
+----------+------------------------------------------------------------------------+-------------+
*/

7.使用[NOT] EXISTS的子查询

如果子查询返回任何行,EXISTS将返回TRUE,否则返回FALSE。

补充:INSERT...SELECT

将查询结果写入数据表

INSERT [INTO] tbl_name [(col_name, ...)]
SELECT ...

example:

CREATE TABLE IF NOT EXISTS tdb_goods_cates(
  cate_id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  cate_name VARCHAR(40)
);
SELECT goods_cate FROM tdb_goods
GROUP BY goods_cate;
/*Result
+---------------+
| goods_cate    |
+---------------+
| 台式机        |
| 平板电脑      |
| 服务器/工作站 |
| 游戏本        |
| 笔记本        |
| 笔记本配件    |
| 超级本        |
+---------------+
*/
INSERT tdb_goods_cates(cate_name)
SELECT goods_cate FROM tdb_goods
GROUP BY goods_cate;
SELECT * FROM tdb_goods_cates;
/*Result
+---------+---------------+
| cate_id | cate_name     |
+---------+---------------+
|       1 | 台式机        |
|       2 | 平板电脑      |
|       3 | 服务器/工作站 |
|       4 | 游戏本        |
|       5 | 笔记本        |
|       6 | 笔记本配件    |
|       7 | 超级本        |
+---------+---------------+
*/

二、多表更新

UPDATE table_references
SET col_name1 = {expr1| DEFAULT}
[, col_name2 = {expr2| DEFAULT}]...
[WHERE where_condition]

example:

UPDATE tdb_goods
INNER JOIN tdb_goods_cates ON goods_cate = cate_name
SET goods_cate = cate_id;
SELECT * FROM tdb_goods;
/*Result
+----------+------------------------------------------------------------------------+------------+------------+-------------+---------+------------+
| goods_id | goods_name                                                             | goods_cate | brand_name | goods_price | is_show | is_saleoff |
+----------+------------------------------------------------------------------------+------------+------------+-------------+---------+------------+
|        1 | R510VC 15.6英寸笔记本                                                  | 5          | 华硕       |    3399.000 |       1 |          0 |
|        2 | Y400N 14.0英寸笔记本电脑                                               | 5          | 联想       |    4899.000 |       1 |          0 |
|        3 | G150TH 15.6英寸游戏本                                                  | 4          | 雷神       |    8499.000 |       1 |          0 |
|        4 | X550CC 15.6英寸笔记本                                                  | 5          | 华硕       |    2799.000 |       1 |          0 |
|        5 | X240(20ALA0EYCD) 12.5英寸超极本                                        | 7          | 联想       |    4999.000 |       1 |          0 |
|        6 | U330P 13.3英寸超极本                                                   | 7          | 联想       |    4299.000 |       1 |          0 |
|        7 | SVP13226SCB 13.3英寸触控超极本                                         | 7          | 索尼       |    7999.000 |       1 |          0 |
|        8 | iPad mini MD531CH/A 7.9英寸平板电脑                                    | 2          | 苹果       |    1998.000 |       1 |          0 |
|        9 | iPad Air MD788CH/A 9.7英寸平板电脑 (16G WiFi版)                      | 2          | 苹果       |    3388.000 |       1 |          0 |
|       10 |  iPad mini ME279CH/A 配备 Retina 显示屏 7.9英寸平板电脑 (16G WiFi版) | 2          | 苹果       |    2788.000 |       1 |          0 |
|       11 | IdeaCentre C340 20英寸一体电脑                                         | 1          | 联想       |    3499.000 |       1 |          0 |
|       12 | Vostro 3800-R1206 台式电脑                                             | 1          | 戴尔       |    2899.000 |       1 |          0 |
|       13 | iMac ME086CH/A 21.5英寸一体电脑                                        | 1          | 苹果       |    9188.000 |       1 |          0 |
|       14 | AT7-7414LP 台式电脑 (i5-3450四核 4G 500G 2G独显 DVD 键鼠 Linux )     | 1          | 宏碁       |    3699.000 |       1 |          0 |
|       15 | Z220SFF F4F06PA工作站                                                  | 3          | 惠普       |    4288.000 |       1 |          0 |
|       16 | PowerEdge T110 II服务器                                                | 3          | 戴尔       |    5388.000 |       1 |          0 |
|       17 | Mac Pro MD878CH/A 专业级台式电脑                                       | 3          | 苹果       |   28888.000 |       1 |          0 |
|       18 |  HMZ-T3W 头戴显示设备                                                  | 6          | 索尼       |    6999.000 |       1 |          0 |
|       19 | 商务双肩背包                                                           | 6          | 索尼       |      99.000 |       1 |          0 |
|       20 | X3250 M4机架式服务器 2583i14                                           | 3          | IBM        |    6888.000 |       1 |          0 |
|       21 |  HMZ-T3W 头戴显示设备                                                  | 6          | 索尼       |    6999.000 |       1 |          0 |
|       22 | 商务双肩背包                                                           | 6          | 索尼       |      99.000 |       1 |          0 |
+----------+------------------------------------------------------------------------+------------+------------+-------------+---------+------------+
*/

三、多表更新之一步到位

CREATE...SELECT

创建数据表同时将查询结果写入到数据表

CREATE TABLE [IF NOT EXISTS] tbl_name
[(create_definition, ...)]
select_statement

example:

SELECT brand_name FROM tdb_goods GROUP BY brand_name;
/*Result
+------------+
| brand_name |
+------------+
| IBM        |
| 华硕       |
| 宏碁       |
| 惠普       |
| 戴尔       |
| 索尼       |
| 联想       |
| 苹果       |
| 雷神       |
+------------+
*/
CREATE TABLE tdb_goods_brands (
  brand_id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  brand_name VARCHAR(40) NOT NULL
) SELECT brand_name FROM tdb_goods GROUP BY brand_name;
SELECT * FROM tdb_goods_brands;
/*Result
+----------+------------+
| brand_id | brand_name |
+----------+------------+
|        1 | IBM        |
|        2 | 华硕       |
|        3 | 宏碁       |
|        4 | 惠普       |
|        5 | 戴尔       |
|        6 | 索尼       |
|        7 | 联想       |
|        8 | 苹果       |
|        9 | 雷神       |
+----------+------------+
*/
UPDATE tdb_goods AS g
INNER JOIN tdb_goods_brands AS b ON g.brand_name = b.brand_name
SET g.brand_name = b.brand_id;
SELECT * FROM tdb_goods;
/*Result
+----------+------------------------------------------------------------------------+------------+------------+-------------+---------+------------+
| goods_id | goods_name                                                             | goods_cate | brand_name | goods_price | is_show | is_saleoff |
+----------+------------------------------------------------------------------------+------------+------------+-------------+---------+------------+
|        1 | R510VC 15.6英寸笔记本                                                  | 5          | 2          |    3399.000 |       1 |          0 |
|        2 | Y400N 14.0英寸笔记本电脑                                               | 5          | 7          |    4899.000 |       1 |          0 |
|        3 | G150TH 15.6英寸游戏本                                                  | 4          | 9          |    8499.000 |       1 |          0 |
|        4 | X550CC 15.6英寸笔记本                                                  | 5          | 2          |    2799.000 |       1 |          0 |
|        5 | X240(20ALA0EYCD) 12.5英寸超极本                                        | 7          | 7          |    4999.000 |       1 |          0 |
......
+----------+------------------------------------------------------------------------+------------+------------+-------------+---------+------------+
*/
ALTER TABLE tdb_goods
CHANGE goods_cate cate_id SMALLINT UNSIGNED NOT NULL,
CHANGE brand_name brand_id SMALLINT NOT NULL;
SHOW COLUMNS FROM tdb_goods;
/*Result
+-------------+------------------------+------+-----+---------+----------------+
| Field       | Type                   | Null | Key | Default | Extra          |
+-------------+------------------------+------+-----+---------+----------------+
| goods_id    | smallint(5) unsigned   | NO   | PRI | NULL    | auto_increment |
| goods_name  | varchar(150)           | NO   |     | NULL    |                |
| cate_id     | smallint(5) unsigned   | NO   |     | NULL    |                |
| brand_id    | smallint(6)            | NO   |     | NULL    |                |
| goods_price | decimal(15,3) unsigned | NO   |     | 0.000   |                |
| is_show     | tinyint(1)             | NO   |     | 1       |                |
| is_saleoff  | tinyint(1)             | NO   |     | 0       |                |
+-------------+------------------------+------+-----+---------+----------------+
*/

四、连接

MySQL在SELECT语句中、多表更新、多表删除语句中支持JOIN操作。

1.语法结构

table_reference
{[INNER| CROSS] JOIN| {LEFT| RIGHT}[OUTER] JOIN}
table_reference
ON conditional_expr

2.数据表参照

table_reference
tbl_name[[AS]alias]|table_subquery[AS]alias

数据表可以使用tbl_name AS alias_name
或tbl_name alias_name赋予别名。
table_subquery可以作为子查询使用在FROM子句中,这样的子查询必须为其赋予别名。

3.链接类型

  • INNER JOIN,内连接
    • 在MySQL中, JOIN, CROSS JOIN和INNER JOIN是等价的。
  • LEFT [OUTER] JOIN,左外连接
  • RIGHT [OUTER] JOIN,右外连接

4.连接条件

使用ON关键词来设定连接条件,也可以使用WHERE来代替。

通常使用ON关键字来设定连接条件,
使用WHERE关键字进行结果集记录的过滤。

5.内连接

显示左表级右表符合连接条件的记录

example:

SELECT goods_id, goods_name, cate_name FROM tdb_goods
INNER JOIN tdb_goods_cates ON tdb_goods.cate_id = tdb_goods_cates.cate_id;
/*Result
+----------+------------------------------------------------------------------------+---------------+
| goods_id | goods_name                                                             | cate_name     |
+----------+------------------------------------------------------------------------+---------------+
|        1 | R510VC 15.6英寸笔记本                                                  | 笔记本        |
|        2 | Y400N 14.0英寸笔记本电脑                                               | 笔记本        |
......
|       21 |  HMZ-T3W 头戴显示设备                                                  | 笔记本配件    |
|       22 | 商务双肩背包                                                           | 笔记本配件    |
+----------+------------------------------------------------------------------------+---------------+
*/

6.左外连接

显示左表的全部记录及右表符合连接条件的记录。

example:

SELECT goods_id, goods_name, cate_name FROM tdb_goods
LEFT JOIN tdb_goods_cates ON tdb_goods.cate_id = tdb_goods_cates.cate_id;
/*Result
+----------+------------------------------------------------------------------------+---------------+
| goods_id | goods_name                                                             | cate_name     |
+----------+------------------------------------------------------------------------+---------------+
......
|       20 | X3250 M4机架式服务器 2583i14                                           | 服务器/工作站 |
|       21 |  HMZ-T3W 头戴显示设备                                                  | 笔记本配件    |
|       22 | 商务双肩背包                                                           | 笔记本配件    |
|       23 |  LaserJet Pro P1606dn 黑白激光打印机                                   | NULL          |
+----------+------------------------------------------------------------------------+---------------+
*/

7.右外连接

显示右表的全部记录及左表符合连接条件的记录

example:

SELECT goods_id, goods_name, cate_name FROM tdb_goods
RIGHT JOIN tdb_goods_cates ON tdb_goods.cate_id = tdb_goods_cates.cate_id;
/*Result
+----------+------------------------------------------------------------------------+---------------+
| goods_id | goods_name                                                             | cate_name     |
+----------+------------------------------------------------------------------------+---------------+
|        1 | R510VC 15.6英寸笔记本                                                  | 笔记本        |
......
|       22 | 商务双肩背包                                                           | 笔记本配件    |
|     NULL | NULL                                                                   | 路由器        |
|     NULL | NULL                                                                   | 交换机        |
|     NULL | NULL                                                                   | 网卡          |
+----------+------------------------------------------------------------------------+---------------+
*/

8.多表连接

SELECT goods_id, goods_name, cate_name, brand_name, goods_price
FROM tdb_goods AS g
INNER JOIN tdb_goods_cates AS c ON g.cate_id = c.cate_id
INNER JOIN tdb_goods_brands AS b ON g.brand_id = b.brand_id;
/*Result
+----------+------------------------------------------------------------------------+---------------+------------+-------------+
| goods_id | goods_name                                                             | cate_name     | brand_name | goods_price |
+----------+------------------------------------------------------------------------+---------------+------------+-------------+
|        1 | R510VC 15.6英寸笔记本                                                  | 笔记本        | 华硕       |    3399.000 |
|        2 | Y400N 14.0英寸笔记本电脑                                               | 笔记本        | 联想       |    4899.000 |
......
|       21 |  HMZ-T3W 头戴显示设备                                                  | 笔记本配件    | 索尼       |    6999.000 |
|       22 | 商务双肩背包                                                           | 笔记本配件    | 索尼       |      99.000 |
+----------+------------------------------------------------------------------------+---------------+------------+-------------+
*/

9.关于连接的几点说明

  • 外链接
A LEFT JOIN B join_condition
  • 数据表B的结果集依赖数据表A。
  • 数据表A的结果集根据左连接条件依赖所有数据表(B表除外)。
  • 左外连接条件决定如何检索数据表B(在没有指定WHERE条件的情况下)。
  • 如果数据表A的某条记录符合WHERE条件,但是在数据表B不存在符合连接条件的记录,将生成一个所有列为空的额外的B行。
  • 如果使用内连接查找的记录在连接数据表中不存在,并且在WHERE子句中尝试以下操作:col_name IS NULL时,如果col_name被定义为NOT NULL,MySQL将在找到符合连接条件的记录后停止搜索更多的行。

10.无限级分类表设计

CREATE TABLE tdb_goods_types(
  type_id   SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, -分类id
  type_name VARCHAR(20) NOT NULL,                         -分类名称
  parent_id SMALLINT UNSIGNED NOT NULL DEFAULT 0          -父类id
);

11.自身连接

同一个数据表对其自身进行连接。

SELECT s.type_id, s.type_name, p.type_name
FROM tdb_goods_types AS s
LEFT JOIN tdb_goods_types AS p ON s.parent_id = p.type_id;
/*Result
+---------+------------+------------+
| type_id | type_name  | type_name  |
+---------+------------+------------+
|       1 | 家用电器   | NULL       |
|       2 | 电脑、办公 | NULL       |
|       3 | 大家电     | 家用电器   |
|       4 | 生活电器   | 家用电器   |
|       5 | 平板电视   | 大家电     |
|       6 | 空调       | 大家电     |
|       7 | 电风扇     | 生活电器   |
|       8 | 饮水机     | 生活电器   |
|       9 | 电脑整机   | 电脑、办公 |
|      10 | 电脑配件   | 电脑、办公 |
|      11 | 笔记本     | 电脑整机   |
|      12 | 超级本     | 电脑整机   |
|      13 | 游戏本     | 电脑整机   |
|      14 | CPU        | 电脑配件   |
|      15 | 主机       | 电脑配件   |
+---------+------------+------------+
*/
SELECT p.type_id, p.type_name, s.type_name
FROM tdb_goods_types AS p
LEFT JOIN tdb_goods_types AS s ON p.type_id = s.parent_id;
/*Result
+---------+------------+-----------+
| type_id | type_name  | type_name |
+---------+------------+-----------+
|       1 | 家用电器   | 大家电    |
|       1 | 家用电器   | 生活电器  |
|       3 | 大家电     | 平板电视  |
|       3 | 大家电     | 空调      |
|       4 | 生活电器   | 电风扇    |
|       4 | 生活电器   | 饮水机    |
|       2 | 电脑、办公 | 电脑整机  |
|       2 | 电脑、办公 | 电脑配件  |
|       9 | 电脑整机   | 笔记本    |
|       9 | 电脑整机   | 超级本    |
|       9 | 电脑整机   | 游戏本    |
|      10 | 电脑配件   | CPU       |
|      10 | 电脑配件   | 主机      |
|       5 | 平板电视   | NULL      |
|       6 | 空调       | NULL      |
|       7 | 电风扇     | NULL      |
|       8 | 饮水机     | NULL      |
|      11 | 笔记本     | NULL      |
|      12 | 超级本     | NULL      |
|      13 | 游戏本     | NULL      |
|      14 | CPU        | NULL      |
|      15 | 主机       | NULL      |
+---------+------------+-----------+
*/
SELECT p.type_id, p.type_name,
count(s.type_name) AS children_count
FROM tdb_goods_types AS p
LEFT JOIN tdb_goods_types AS s ON s.parent_id = p.type_id
GROUP BY p.type_name
ORDER BY p.type_id;
/*Result
+---------+------------+---------------+
| type_id | type_name  | children_coun |
+---------+------------+---------------+
|       1 | 家用电器   |             2 |
|       2 | 电脑、办公 |             2 |
|       3 | 大家电     |             2 |
|       4 | 生活电器   |             2 |
|       5 | 平板电视   |             0 |
|       6 | 空调       |             0 |
|       7 | 电风扇     |             0 |
|       8 | 饮水机     |             0 |
|       9 | 电脑整机   |             3 |
|      10 | 电脑配件   |             2 |
|      11 | 笔记本     |             0 |
|      12 | 超级本     |             0 |
|      13 | 游戏本     |             0 |
|      14 | CPU        |             0 |
|      15 | 主机       |             0 |
+---------+------------+---------------+
*/

12.多表删除

DELETE tbl_name[.*][, tbl_name[.*]]...
FROM table_references
[WHERE where_condition]

example:

-- 查找重复记录
SELECT goods_id,goods_name FROM tdb_goods
GROUP BY goods_name HAVING count(goods_name) >= 2;
/*Result
+----------+-----------------------+
| goods_id | goods_name            |
+----------+-----------------------+
|       18 |  HMZ-T3W 头戴显示设备 |
|       19 | 商务双肩背包          |
+----------+-----------------------+
*/
-- 删除重复记录
DELETE t1 FROM tdb_goods AS t1
LEFT JOIN (
  SELECT goods_id,goods_name
  FROM tdb_goods
  GROUP BY goods_name HAVING count(goods_name) >= 2
) AS t2  
ON t1.goods_name = t2.goods_name  
WHERE t1.goods_id > t2.goods_id;
/*Result
+----------+------------------------------------------------------------------------+---------+----------+-------------+---------+------------+
| goods_id | goods_name                                                             | cate_id | brand_id | goods_price | is_show | is_saleoff |
+----------+------------------------------------------------------------------------+---------+----------+-------------+---------+------------+
|        1 | R510VC 15.6英寸笔记本                                                  |       5 |        2 |    3399.000 |       1 |          0 |
|        2 | Y400N 14.0英寸笔记本电脑                                               |       5 |        7 |    4899.000 |       1 |          0 |
|        3 | G150TH 15.6英寸游戏本                                                  |       4 |        9 |    8499.000 |       1 |          0 |
|        4 | X550CC 15.6英寸笔记本                                                  |       5 |        2 |    2799.000 |       1 |          0 |
|        5 | X240(20ALA0EYCD) 12.5英寸超极本                                        |       7 |        7 |    4999.000 |       1 |          0 |
|        6 | U330P 13.3英寸超极本                                                   |       7 |        7 |    4299.000 |       1 |          0 |
|        7 | SVP13226SCB 13.3英寸触控超极本                                         |       7 |        6 |    7999.000 |       1 |          0 |
|        8 | iPad mini MD531CH/A 7.9英寸平板电脑                                    |       2 |        8 |    1998.000 |       1 |          0 |
|        9 | iPad Air MD788CH/A 9.7英寸平板电脑 (16G WiFi版)                      |       2 |        8 |    3388.000 |       1 |          0 |
|       10 |  iPad mini ME279CH/A 配备 Retina 显示屏 7.9英寸平板电脑 (16G WiFi版) |       2 |        8 |    2788.000 |       1 |          0 |
|       11 | IdeaCentre C340 20英寸一体电脑                                         |       1 |        7 |    3499.000 |       1 |          0 |
|       12 | Vostro 3800-R1206 台式电脑                                             |       1 |        5 |    2899.000 |       1 |          0 |
|       13 | iMac ME086CH/A 21.5英寸一体电脑                                        |       1 |        8 |    9188.000 |       1 |          0 |
|       14 | AT7-7414LP 台式电脑 (i5-3450四核 4G 500G 2G独显 DVD 键鼠 Linux )     |       1 |        3 |    3699.000 |       1 |          0 |
|       15 | Z220SFF F4F06PA工作站                                                  |       3 |        4 |    4288.000 |       1 |          0 |
|       16 | PowerEdge T110 II服务器                                                |       3 |        5 |    5388.000 |       1 |          0 |
|       17 | Mac Pro MD878CH/A 专业级台式电脑                                       |       3 |        8 |   28888.000 |       1 |          0 |
|       18 |  HMZ-T3W 头戴显示设备                                                  |       6 |        6 |    6999.000 |       1 |          0 |
|       19 | 商务双肩背包                                                           |       6 |        6 |      99.000 |       1 |          0 |
|       20 | X3250 M4机架式服务器 2583i14                                           |       3 |        1 |    6888.000 |       1 |          0 |
|       23 |  LaserJet Pro P1606dn 黑白激光打印机                                   |      12 |        4 |    1849.000 |       1 |          0 |
+----------+------------------------------------------------------------------------+---------+----------+-------------+---------+------------+
*/

你可能感兴趣的:(第五章 子查询与连接)