【MySQL:视频笔记3】select的查询模型,子查询

查询模型

  • 列就是变量,在每一行上,列的值都在变化
  • where条件是表达式,在哪一行表达式为真,哪一行就取出来
  • 查询结果集可以当成表看

1、熟练运算符in和not的用法

运算符 说明
in 某个集合内
between and 某个范围内
not 或 ! 逻辑非

like里的_ 匹配单一字符

2、where的注意事项

where 1; --all 
where 0; --empty

比如
select * from tbname where 1>2; -- empty

3、广义投影

mysql> #取出商品价比市场价省的钱
mysql> select goods_id,goods_name,(market_price-shop_price) as discount from goods;

#这一列即是运算结果,术语为“广义投影”
#即把列看成变量,可以运算
#取出商品价比市场价省的钱,并且大于200
mysql> select goods_id,goods_name,(market_price-shop_price) as discount from goods where (market_price-shop_price) >200;
而不能这样 where discount >200,因为 where 字句只针对原表中的数据,而discount是已经查询出的结果,用`having` 

这里写图片描述


4、面试题

把数字[20,29]改为20,[30,39]改为30


mysql> select * from mst;
+------+
| num  |
+------+
|    1 |
|   13 |
|   25 |
|   27 |
|   29 |
|   32 |
|   35 |
|   35 |
|   45 |
|   46 |
+------+
10 rows in set (0.00 sec)

mysql> update mst set num=floor(num/10)*10 where num between 20 and 39;

把有前缀“诺基亚”的商品名改为“HTC”

mysql> select goods_id,goods_name,concat('HTC',substring(goods_name,4)) from goo
ds where goods_name like "诺基亚%";
+----------+---------------------+---------------------------------------+
| goods_id | goods_name          | concat('HTC',substring(goods_name,4)) |
+----------+---------------------+---------------------------------------+
|        4 | 诺基亚N85原装充电器              | HTCN85原装充电器
              |
|        9 | 诺基亚E66                | HTCE66                                |
|       14 | 诺基亚5800XM             | HTC5800XM                             |
|       32 | 诺基亚N85                | HTCN85                                |
+----------+---------------------+---------------------------------------+

COUNT(expr)函数

  • COUNT(colname) 返回SELECT语句检索到的行中非NULL值的数目。 若找不到匹配的行,则COUNT() 返回 0 。
  • COUNT(*) 返回检索行的包含 NULL值的数目

mysql> SELECT * from test_count;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 |
|    2 | NULL |
| NULL | NULL |
+------+------+

mysql> select count(id) from test_count;
+-----------+
| count(id) |
+-----------+
|         2 |
+-----------+

mysql> select count(num) from test_count;
+------------+
| count(num) |
+------------+
|          1 |
+------------+

mysql> select count(*) from test_count;
+----------+
| count(*) |
+----------+
|        3 |
+----------+

mysql> select count(1) from test_count;
+----------+
| count(1) |
+----------+
|        3 |
+----------+

count(*)和count(1)区别

  • 在MyISAM中,无区别。因为引擎内有个计数器在维护着行数,行数可直接统计出来
  • 在innoDB中,用count(*)直接读取行数,效率很低,因为引擎会一行一行数一遍

GROUP

  • 取数据第一次出现的行
#分类统计商品数量
mysql> select cat_id,sum(goods_number) from goods group by cat_id;
+--------+-------------------+
| cat_id | sum(goods_number) |
+--------+-------------------+
|      3 |                 6 |
|      4 |                 2 |
|      6 |                 3 |
|      8 |                19 |
|     16 |                 6 |
|     18 |                 1 |
|     19 |                10 |
|     20 |                 1 |
|     22 |                 1 |
|     24 |                64 |
|     25 |               998 |
+--------+-------------------+

分析以下sql

mysql> select goods_id,sum(goods_number) from goods;
+----------+-------------------+
| goods_id | sum(goods_number) |
+----------+-------------------+
|        1 |              1111 |
+----------+-------------------+

该语句可以执行,并且把goods_id第一次出现的值取出来了。
对于sql标准来说,该语句是错误的,不能执行的,因为语意有问题。
但是mysql可以,因为这是它的一个特点,出于可移植性和规范性,不推荐这么写

严格来说,group by a,b,c 为列,则select的列只能在a,b,c 里选择,才没有语意矛盾


HAVING

  • 表的数据
    where
  • 查询出满足条件的行
    计算函数,group
  • 结果集(广义投影)
    having
  • 最终结果集

where 针对表,having针对结果集

这里写图片描述
这里写图片描述

#查询本店价与市场价省的钱,并且省钱大于200
mysql> select goods_id,goods_name,(market_price-shop_price) as discount from goo
ds
    -> where 1
    -> having discount > 200;
+----------+--------------+----------+
| goods_id | goods_name   | discount |
+----------+--------------+----------+
|        1 | KD876        |   277.60 |
|        9 | 诺基亚E66         |   459.60 |
|       69 | 平衡车           |   399.79 |
|       14 | 诺基亚5800XM      |   525.00 |
|       32 | 诺基亚N85         |   602.00 |
+----------+--------------+----------+
#查询积压货款超过1w的栏目及其积压的货款
mysql> select cat_id,sum(goods_number*shop_price) as m from goods
    -> group by cat_id
    -> having m > 10000;
+--------+-----------+
| cat_id | m         |
+--------+-----------+
|      3 |  16636.00 |
|     25 | 996004.00 |
+--------+-----------+

练习题

//where-group-having
//查询挂科两门及两门以上的学员平均分
//(题目解释:学员全部科目的平均分,并且为挂机两门以上(包括两门)的科目)
 +------+---------+-------+
| name | subject | score |
+------+---------+-------+
| 张三     | 数学       |    90 |
| 张三     | 语文        |    50 |
| 张三     | 地理        |    40 |
| 李四     | 语文        |    55 |
| 李四     | 政治        |    45 |
| 王五     | 政治        |    30 |
+------+---------+-------+


#求平均分=》筛选挂数
mysql> select name,avg(score),sum(score<60) as gks from result
    -> group by name having gks>=2;
+------+------------+------+
| name | avg(score) | gks  |
+------+------------+------+
| 张三     |    60.0000 |    2 |
| 李四     |    50.0000 |    2 |
+------+------------+------+


#筛挂科数=》求平均分
mysql> select name,avg(score) from result
    -> where name in (select name from (select name,count(1) as gks from result where score<60 group by name having gks>=2) as temp)
    -> GROUP BY name;
+------+------------+
| name | avg(score) |
+------+------------+
| 张三     |    60.0000 |
| 李四     |    50.0000 |
+------+------------+
2 rows in set (0.00 sec)

ORDER

  • 排序对象:结果集
  • 书写语法:order colname1 asc/desc,colname asc/desc…
  • 排序优先级:左高右低

这里写图片描述


LIMIT

  • 书写语法:limit [offset,],N
  • offset:偏移量。及忽略前面的条目数
  • N:查询的条目数
mysql> select goods_id,goods_name,cat_id,shop_price from goods
    -> order by cat_id,shop_price desc
    -> limit 2,3;
+----------+--------------+--------+------------+
| goods_id | goods_name   | cat_id | shop_price |
+----------+--------------+--------+------------+
|        8 | 飞利浦9@9v         |      3 |     399.00 |
|       14 | 诺基亚5800XM      |      4 |    2625.00 |
|        1 | KD876        |      4 |    1388.00 |
+----------+--------------+--------+------------+
3 rows in set (0.00 sec)

子查询

  • where型子查询:把内层查询结果作为外层查询的比较条件
    如果 where 列=(内层sql),则内层sql返回的必是单行单列单个值
    如果 where 列 in (内层sql),则内层sql只返回单列,可多行
  • from型子查询:内层sql的查询结果,当成临时表,供外层sql再次查询
  • exists型子查询:把外层查询结果拿到内层sql测试,如果成立,则取出

子句书写顺序和执行优先级:where => group => having => order => limit

练习题

//取出每个cat_id下最大的goods_id

mysql> select cat_id,goods_id from goods
    -> order by cat_id,goods_id desc;
+--------+----------+
| cat_id | goods_id |
+--------+----------+
|      3 |       32 |
|      3 |        9 |
|      3 |        8 |
|      4 |       14 |
|      4 |        1 |
|      6 |       60 |
|      6 |       59 |
|      6 |       54 |
|      8 |       53 |
|      8 |       52 |
|      8 |        4 |
|     16 |       48 |
|     16 |       47 |
|     16 |       46 |
|     16 |       44 |
|     16 |       43 |
|     16 |       42 |
|     18 |       36 |
|     19 |       51 |
|     19 |       50 |
|     19 |       49 |
|     19 |       45 |
|     19 |       41 |
|     19 |       40 |
|     19 |       39 |
|     19 |       38 |
|     19 |       37 |
|     19 |       35 |
|     20 |       58 |
|     22 |       55 |
|     24 |       72 |
|     24 |       70 |
|     24 |       69 |
|     24 |       68 |
|     24 |       64 |
|     24 |       63 |
|     24 |       62 |
|     24 |       61 |
|     25 |       73 |
+--------+----------+
39 rows in set (0.00 sec)


1.WHERE型

SELECT
    *
FROM
    (
        SELECT
            cat_id,
            goods_id,
            goods_name
        FROM
            goods
        ORDER BY
            cat_id,
            goods_id DESC
    ) AS temp
GROUP BY
    cat_id
ORDER BY
    cat_id;


2.FROM型

SELECT
    cat_id,
    goods_id,
    goods_name
FROM
    goods
WHERE
    goods_id IN (
        SELECT
            max(goods_id)
        FROM
            goods
        GROUP BY
            cat_id
    )
ORDER BY
    cat_id;
//exists型
//把goods栏目下有商品的取出来

category表
+--------+----------+
| cat_id | cat_name |
+--------+----------+
|      1 | 手机类型        |
|      3 | 小型手机       |
|      4 | 3G手机      |
|      6 | 手机        |
|      8 | 耳机         |
|      9 | 电池         |
|     12 | 充值卡        |
|     16 | 服装        |
|     18 | 智能硬件        |
|     19 | 配件         |
|     20 | 保护壳         |
|     22 | 移动电源       |
|     24 | 数码时尚        |
+--------+----------+

goods表
+--------+----------+-------------------------------------+
| cat_id | goods_id | goods_name                          |
+--------+----------+-------------------------------------+
|      3 |        8 | 飞利浦9@9v                                |
|      4 |        1 | KD876                               |
|      6 |       54 | 插线板                                   |
|      8 |        4 | 诺基亚N85原装充电器                              
|     16 |       42 | 短袖T恤 米兔大游行                                                    
|     18 |       36 | 路由器                                   |
|     19 |       35 | 体重秤                                   |
|     20 |       58 | 手机3高配版 超薄钢化玻璃膜(0.22mm)                       
|     22 |       55 | 移动电源10000mAh                          |
|     24 |       61 | 视频                                   |
+--------+----------+-------------------------------------+


mysql> select cat_id,cat_name from category
    -> where exists (select * from goods where goods.cat_id=category.cat_id);
+--------+----------+
| cat_id | cat_name |
+--------+----------+
|      3 | 小型手机       |
|      4 | 3G手机      |
|      6 | 手机        |
|      8 | 耳机         |
|     16 | 服装        |
|     18 | 智能硬件        |
|     19 | 配件         |
|     20 | 保护壳         |
|     25 | 数码时尚        |
|     22 | 移动电源       |
|     24 | 数码时尚        |
+--------+----------+
11 rows in set (0.02 sec)

NULL

这里写图片描述


mysql> select * from test2;
+-------+
| sname |
+-------+
| 张三      |
| 李四      |
| NULL  |
+-------+
3 rows in set (0.00 sec)

mysql> select * from test2 where sname is not null;
+-------+
| sname |
+-------+
| 张三      |
| 李四      |
+-------+
2 rows in set (0.02 sec)

mysql> select * from test2 where sname is null;
+-------+
| sname |
+-------+
| NULL  |
+-------+
1 row in set (0.00 sec)

mysql> select * from test2 where sname=null;
Empty set (0.00 sec)

mysql> select * from test2 where sname!=null;
Empty set (0.00 sec)

mysql> select 2>1;
+-----+
| 2>1 |
+-----+
|   1 |
+-----+
1 row in set (0.00 sec)

mysql> select 1>2;
+-----+
| 1>2 |
+-----+
|   0 |
+-----+
1 row in set (0.00 sec)

mysql> select 2*3;
+-----+
| 2*3 |
+-----+
|   6 |
+-----+
1 row in set (0.00 sec)

mysql> select null=null;
+-----------+
| null=null |
+-----------+
|      NULL |
+-----------+
1 row in set (0.00 sec)

mysql> select null!=null;
+------------+
| null!=null |
+------------+
|       NULL |
+------------+

猜你喜欢

转载自blog.csdn.net/qq_39251267/article/details/80249795