美文网首页
【MySQL】MySQL查询——子查询

【MySQL】MySQL查询——子查询

作者: 感同身受_ | 来源:发表于2020-01-30 10:23 被阅读0次
  1. 查出本网站,最新的(goods_id最大)的商品
    select goods_id,goods_name,cat_id from goods order by goods_id desc limit 1;
  2. 查出本网站,最新的(goods_id最大)的商品,不能用排序方法
    select goods_id,goods_name,cat_id,max(goods_id) from goods having goods_id=33;
    这里是我们已知最大的goods_id是33,但如果我们不知道呢,所以,我们需要用一个表返回最大的goods_id:select max(goods_id) from goods;
    然后用where判断goods_id与查出来的最大值相等:
    select goods_id,goods_name,cat_id,max(goods_id) from goods where goods_id=(select max(goods_id) from goods);
  3. 总结:
    以后凡需要查出最新商品,先用max()查出最大的goods_id,然后在根据goods_id查询商品
    就是以后商品表再怎么边,delect max()语句的返回值,始终是指向最大的goods_id的
查出每个栏目下的最新(goods_id最大)的商品
  1. 用where子查询解:
    第一步,先求出每个栏目下的最大的goods_id:
    select max(goods_id),cat_id from goods group by cat_id order by cat_id asc;
    第二步,我们只要把goods_id=(16,32,18...28)这几个商品取出来
    select goods_id,goods_name,shop_price,cat_id from goods where goods_id in (select max(goods_id) from goods group by cat_id order by cat_id asc);
  2. 用from子查询解
    select goods_id,cat_id,goods_name from goods order by cat_id asc,goods_id desc;
    select * from (select goods_id,cat_id,goods_name from goods order by cat_id asc,goods_id desc) as tmp group by cat_id;

子查询类型:

  1. where型子查询:把内层查询的结果作为外层查询的比较条件,
    典型题:查询最大商品、最贵商品
    所以
    特点:
    如果where 列=(内层 sql),则内层sql返回的必是单行单列,单个值
    如果where 列 in (内层 sql),则内层sql只返回单列,可以多行
  2. from型子查询
    【注】查询结果集在结果上可以当成表看
    内层sql的查询结果,当成一张临时表,供外层sql,再次查询
  3. existe型子查询
    是指 把外层sql的结果,拿到内层sql去测试,如果内层sql成立,则该行取出
    建一个category表:
mysql> select * from category;
+--------+-------------------+-----------+
| cat_id | cat_name          | parent_id |
+--------+-------------------+-----------+
|      1 | 手机类型                 |         0 |
|      2 | CDMA手机             |         1 |
|      3 | GSM手机              |         1 |
|      4 | 3G手机               |         1 |
|      5 | 双模手机               |         1 |
|      6 | 手机配件                 |         0 |
|      7 | 充电器                  |         6 |
|      8 | 耳机                  |         6 |
|      9 | 电池                  |         6 |
|     11 | 读卡器和内存卡               |         6 |
|     12 | 充值卡                 |         0 |
|     13 | 小灵通/固话充值卡             |        12 |
|     14 | 移动手机充值卡               |        12 |
|     15 | 联通手机充值卡               |        12 |
+--------+-------------------+-----------+
14 rows in set (0.03 sec)

要求:别把14个栏目都取出来,只把下面有商品的栏目取出来
思路:设某栏目cat_id为N,则select * from goods where cat_id=N
能取出数据,则说明该栏目有商品
select cat_id,cat_name from category where exists (select * from goods where goods.cat_id=category.cat_id);

建表语句解析:

  1. 建表时,列后面not null default '',default 0,是什么意思?
    答:就是让这个列不为null,如果某个列确实没值,也有默认值,也不为null
  2. 为什么不希望列的值为null?
    判断字符串是否为null
    select lisi=null;
    select null=null;
    delect null!=null;
    以上三句的返回值都是NULL
    我们知道,null是空,若要和他进行比较,需要用到特殊的运算符:is null,is not null
    答:
    A:不好比较:
    null是一种类型,比较时,只能用专门的is null和is not null来比较,碰到运算符,一律返回null
    B:效率不高:
    影响索引效率
    因此,在建表时,我们一般采用
    not null default ""/0;

表与集合的关系:
一张表就是一个集合
每一行就是一个元素
集合有唯一性,所以一张表里面不可能有数据完全相同的一行,这个由mysql内部控制

  1. 两个集合相乘:
mysql> create table test10 (
    -> id int,
    -> sname char(20)
    -> )engine myisam charset utf8;
Query OK, 0 rows affected (0.14 sec)

mysql> create table test11 (
    -> id int,
    -> sname char(20)
    -> )engine myisam charset utf8;
Query OK, 0 rows affected (0.02 sec)

mysql> set names gbk;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into test10
    -> values    ,
    -> (1,'云彩'),
    -> (2,'月亮'),
    -> (3,'星星1');
Query OK, 3 rows affected (0.10 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> insert into test11
    -> values     ,
    -> (95,'猴子'),
    -> (96,'老虎');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from test10,test11;
+------+-------+------+-------+
| id   | sname | id   | sname |
+------+-------+------+-------+
|    1 | 云彩     |   95 | 猴子      |
|    1 | 云彩     |   96 | 老虎     |
|    2 | 月亮      |   95 | 猴子      |
|    2 | 月亮      |   96 | 老虎     |
|    3 | 星星1     |   95 | 猴子      |
|    3 | 星星1     |   96 | 老虎     |
+------+-------+------+-------+
6 rows in set (0.01 sec)

左连接的语法:

假设A表在左,不动,B表在A表的右边滑动
A表与B表通过一个关系来筛选B表的行
语法:
A left join B on 条件 ——条件为真,则B对应的行取出
【注】A left join B,并不是说A表的就一定在左边,只是说在查询数据时,以A表为准,显示的数据顺序是根据自己select后面的内容指定的,如:select sname,id from A left join B on ...
A left join B on 条件
这一块形成的也是一个结果集,可以看成一张表,设为C
既如此,可以对 C表作查询,自然where,group,order by,limit,,having等等都可以使用

问:C表可以查询的列有哪些列?
答:A,B的列都可以查

mysql> select goods_name,goods_id,goods_number,cat_name,shop_price from goods left join category on goods.cat_id = category.cat_id;
+------------------------------+----------+--------------+-------------------+------------+
| goods_name                   | goods_id | goods_number | cat_name          | shop_price |
+------------------------------+----------+--------------+-------------------+------------+
| kd876                        |        1 |            1 | 3G手机               |    1388.00 |
| 诺基亚n85原装充电器                       |        4 |           17 | 耳机                  |      58.00 |
| 诺基亚原装5800耳机                      |        3 |           24 | 耳机                  |      68.00 |
| 索爱原装m2卡读卡器                         |        5 |            8 | 读卡器和内存卡               |      20.00 |
| 胜创kingmax内存卡                  |        6 |           15 | 读卡器和内存卡               |      42.00 |
| 诺基亚n85原装立体声耳机hs-82                  |        7 |           20 | 耳机                  |     100.00 |
| 飞利浦9@9v                         |        8 |            1 | GSM手机              |     399.00 |
| 诺基亚e66                         |        9 |            4 | GSM手机              |    2298.00 |
| 索爱c702c                        |       10 |            7 | GSM手机              |    1328.00 |
| 索爱c702c                        |       11 |            1 | GSM手机              |    1300.00 |
| 摩托罗拉a810                        |       12 |            8 | GSM手机              |     983.00 |
| 诺基亚5320 xpressmusic            |       13 |            8 | GSM手机              |    1311.00 |
| 诺基亚5800xm                      |       14 |            1 | 3G手机               |    2625.00 |
| 摩托罗拉a810                        |       15 |            3 | GSM手机              |     788.00 |
| 恒基伟业g101                       |       16 |            0 | CDMA手机             |     823.33 |
| 夏新n7                           |       17 |            1 | GSM手机              |    2300.00 |
| 夏新t5                           |       18 |            1 | 3G手机               |    2878.00 |
| 三星sgh-f258                     |       19 |           12 | GSM手机              |     858.00 |
| 三星bc01                         |       20 |           12 | GSM手机              |     280.00 |
| 金立 a30                         |       21 |           40 | GSM手机              |    2000.00 |
| 多普达touch hd                    |       22 |            1 | GSM手机              |    5999.00 |
| 诺基亚n96                         |       23 |            8 | 双模手机               |    3700.00 |
| p806                         |       24 |          100 | GSM手机              |    2000.00 |
| 小灵通/固话50元充值卡                     |       25 |            2 | 小灵通/固话充值卡             |      48.00 |
| 小灵通/固话20元充值卡                     |       26 |            2 | 小灵通/固话充值卡             |      19.00 |
| 联通100元充值卡                       |       27 |            2 | 联通手机充值卡               |      95.00 |
| 联通50元充值卡                        |       28 |            0 | 联通手机充值卡               |      45.00 |
| 移动100元充值卡                       |       29 |            0 | 移动手机充值卡               |      90.00 |
| 移动20元充值卡                        |       30 |            9 | 移动手机充值卡               |      18.00 |
| 摩托罗拉e8                          |       31 |            1 | GSM手机              |    1337.00 |
| 诺基亚n85                         |       32 |            4 | GSM手机              |    3010.00 |
+------------------------------+----------+--------------+-------------------+------------+
31 rows in set (0.00 sec)

左连接之后的表也可以用where等语句:

mysql> select goods_name,goods_id,goods_number,cat_name,goods.cat_id,shop_price from goods left join category on goods.cat_id = category.cat_id where goods.cat_id = 4;
+--------------+----------+--------------+----------+--------+------------+
| goods_name   | goods_id | goods_number | cat_name | cat_id | shop_price |
+--------------+----------+--------------+----------+--------+------------+
| kd876        |        1 |            1 | 3G手机      |      4 |    1388.00 |
| 诺基亚5800xm      |       14 |            1 | 3G手机      |      4 |    2625.00 |
| 夏新t5           |       18 |            1 | 3G手机      |      4 |    2878.00 |
+--------------+----------+--------------+----------+--------+------------+
3 rows in set (0.02 sec)

左连接、右连接、内连接的区别:

  1. 左右连接是可以互换的:A left join B = B right join A
    【注】既然左右连接可以互换,尽量用左连接,出于移植时兼容性方面的考虑
  2. 内连接的特点
    A inner join B
    A inner join Bleft join/right join的关系:
    内连接是左右连接的交集
    【注】mysql中不支持外连接
小练习

Match的hostTeamID与guestTeamID都与Team中的teamID关联
查出2006-6-1到2006-7-1之间的所有比赛,并且用一下形式列出:
拜仁 2:0 不来梅 2006-6-21

  1. 建表
create table m (
mid int ,
hid int,
gid int,
mres varchar(10),
matime date
)engine myisam charset utf8;

create table t(
tid int,
tname varchar(20)
)engine myisam charset utf8;

【注】match为mysql的关键字

mysql> create table match (
    -> mid int ,
    -> hid int,
    -> gid int,
    -> mres varchar(10),
    -> matime date
    -> )engine myisam charset utf8;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'match (
mid int ,
hid int,
gid int,
mres varchar(10),
matime date
)engine myisam' at line 1
  1. 解题:
#将id与name关联
mysql> select hid,t1.tname,mres,gid,t2.tname,matime
    -> from
    -> (m left join t as t1 on hid=t1.tid)
    -> left join t as t2 on gid=t2.tid;
+------+----------+------+------+----------+------------+
| hid  | tname    | mres | gid  | tname    | matime     |
+------+----------+------+------+----------+------------+
|    1 | 国安         | 2:0  |    2 | 申花       | 2006-05-21 |
|    2 | 申花       | 1:2  |    3 | 布尔联队         | 2006-06-21 |
|    3 | 布尔联队         | 2:5  |    1 | 国安         | 2006-06-25 |
|    2 | 申花       | 3:2  |    1 | 国安         | 2006-07-21 |
+------+----------+------+------+----------+------------+
4 rows in set (0.00 sec)

#最终结果
mysql> select hid,t1.tname,mres,gid,t2.tname,matime
    -> from
    -> (m left join t as t1 on hid=t1.tid)
    -> left join t as t2 on gid=t2.tid
    -> where matime between '2006-06-01' and '2006-07-01';
+------+----------+------+------+----------+------------+
| hid  | tname    | mres | gid  | tname    | matime     |
+------+----------+------+------+----------+------------+
|    2 | 申花       | 1:2  |    3 | 布尔联队         | 2006-06-21 |
|    3 | 布尔联队         | 2:5  |    1 | 国安         | 2006-06-25 |
+------+----------+------+------+----------+------------+
2 rows in set (0.36 sec)

33集

相关文章

  • MySQL 子查询、内联结、外联结

    子查询MySQL 子查询版本要求:MySQL4.1引入了对子查询的支持。子查询:嵌套在其他查询语句中的查询。 示例...

  • mysql 查询

    mysql的查询、子查询及连接查询 一、mysql查询的五种子句 where(条件查询)、having(筛选)、g...

  • 【MySQL】MySQL查询——子查询

    查出本网站,最新的(goods_id最大)的商品select goods_id,goods_name,cat_id...

  • 查询性能优化

    MySQL查询优化器的局限性 关联子查询 MySQL的子查询实现的非常糟糕,最糟糕的一类查询是where条件中包含...

  • 第六章 查询性能优化(下)

    MySQL查询优化器的局限性 关联子查询 MySQL的关联子查询实现的很差,最好改成左外连接(LEFT OUTER...

  • MySQL--基础二

    本节总结MySQL的筛选条件,聚合与分组,子查询,连接查询。 MySQL的筛选条件 MySQL中的比较运算符: 比...

  • mysql 查询 - 个人记录

    1.mysql 子查询使用父查询字段作为条件,查询B表数量 2.mysql 根据某字段排行,获取当前用户排名

  • MySql查询-子查询

    子查询 在一个 select 语句中,嵌入了另外一个 select 语句, 那么被嵌入的 select 语句称之为...

  • 2018-03-20

    MYSQL查询语句 MYSQL复杂操作语句 MYSQL多表查询方法 函数部分

  • 高性能的索引策略

    MySQL查询基础-查询执行过程 MySQL聚簇索引 MySQL覆盖索引 MySQL索引扫描排序 MySQL冗余和...

网友评论

      本文标题:【MySQL】MySQL查询——子查询

      本文链接:https://www.haomeiwen.com/subject/jxlzjctx.html