【MYSQL】表的综合查询

MySQL的比较运算和逻辑运算符:

比较运算符号描述
=等于
<>, !=不等于
>大于
<小于
<=小于等于
>=大于等于
BETWEEN在两值之间 >=min&&<=max
NOT BETWEEN不在两值之间
IN在集合中
NOT IN不在集合中
<=, >=严格比较两个NULL值是否相等 两个操作码均为NULL时,其所得值为1;而当一个操作码为NULL时,其所得值为0
LIKE模糊匹配
REGEXP 或 RLIKE正则式匹配
IS NULL为空
IS NOT NULL不为空
逻辑运算符号作用
NOT 或 !逻辑非
AND逻辑与
OR逻辑或
XOR逻辑异或

注意事项:

  • and比or的优先级高,当表达式比较复杂时,习惯使用括号,避免出现歧义。
  • in用法:in的后面跟着枚举,例如in (3,11)
  • between通常和 and连用,例如 between 100 and 500

示例表数据如下:

1. where 条件约束

where是针对磁盘数据文件,后面一般都是列变量的表达式。模糊查询时,百分号%表示匹配所有字符,下划线_表示匹配一个字符。

# ⑴ 主键为32的商品
SELECT goods_id,goods_name,shop_price FROM goods WHERE goods_id=32;

# ⑵ 不属第3栏目的所有商品
SELECT cat_id,goods_name,shop_price FROM goods WHERE cat_id!=3;

# ⑶ 本店价格高于3000元的商品
SELECT goods_id,goods_name,shop_price FROM goods WHERE shop_price>3000;

# ⑷ 本店价格低于或等于100元的商品
SELECT goods_id,goods_name,shop_price FROM goods WHERE shop_price<=100;

# ⑸ 取出第4栏目或第11栏目的商品(不用or)
SELECT cat_id,goods_name,shop_price FROM goods WHERE cat_id IN (4,11);

# ⑹ 取出100<=价格<=500的商品(不许用and)
SELECT goods_id,goods_name,shop_price FROM goods WHERE shop_price BETWEEN 100 AND 500;

# ⑺ 不属于第3栏目且不属于第11栏目的商品(and,或not in分别实现)
SELECT cat_id,goods_name,shop_price FROM goods WHERE (cat_id!=3) && (cat_id!=11);
SELECT cat_id,goods_name,shop_price FROM goods WHERE cat_id NOT IN (3,11);

# ⑻ 取出价格大于100且小于300,或者大于3000小于4000商品
SELECT goods_id,goods_name,shop_price FROM goods WHERE (shop_price>100 && shop_price<300) || (shop_price>3000 && shop_price<4000);

# ⑼ 取出第3个栏目下面价格<1000或>3000,并且点击量>5的系列商品
SELECT cat_id,goods_name,shop_price,click_count FROM goods WHERE (cat_id=3) && (shop_price<1000 || shop_price>3000) && (click_count>=5);

# ⑽ 取出第1个栏目下面的商品(注意:第1栏目下面没商品,但其子栏目下有)
SELECT cat_id,goods_name,shop_price FROM goods WHERE cat_id IN (2,3,4,5);# 手动查看第1栏目的子栏目有2 3 4 5

# ⑾ 取出名字以"诺基亚"开头的商品
SELECT cat_id,goods_name,shop_price FROM goods WHERE goods_name LIKE '诺基亚%';

# ⑿ 取出诺基亚N系列的手机
SELECT goods_id,goods_name,shop_price FROM goods WHERE goods_name LIKE '诺基亚N__';

# ⒀ 取出名字不以"诺基亚"开头的商品
SELECT goods_id,goods_name,shop_price FROM goods WHERE goods_name NOT LIKE '诺基亚%';

# ⒁ 取出第3个栏目下面价格在1000到3000之间,并且点击量>5 的"诺基亚"开头的商品
SELECT cat_id,goods_name,shop_price,click_count FROM goods WHERE (cat_id=3) && (shop_price>1000 && shop_price<3000) && (click_count>5) && (goods_name LIKE '诺基亚%');

# ⒂ 把num值处于[20,29]之间,改为20,num值处于[30,39]之间的,改为30
UPDATE mian SET num=floor(num/10)*10 WHERE num BETWEEN 20 AND 39;

# ⒃ 把good表中商品名为'诺基亚xxxx'的商品,改为'HTCxxxx'
UPDATE goods SET goods_name=INSERT(goods_name,1,3,'HTC') WHERE goods_name LIKE '诺基亚%'; # 注:字符串位置从1开始

2. group 数据分组

使用group时首先会对该列重新排序,再做统计,所以比较耗资源,尽量避免使用。

# ⑴ 查出最贵和最便宜的商品的价格
SELECT max(shop_price),min(shop_price) FROM goods;

# ⑵ 查出最新和最旧的商品编号
SELECT max(goods_id),min(goods_id) FROM goods;

# ⑶ 查询该店所有商品的库存总量
SELECT sum(goods_number) FROM goods;

# ⑷ 查询所有商品的平均价格
SELECT avg(shop_price) FROM goods;

# ⑸ 查询该店一共有多少种商品
SELECT count(*) FROM goods;

# ⑹ 查询每个栏目下面最贵商品价格、最便宜商品价格、商品平均价格、商品库存量、商品库存总价格、商品种类
SELECT max(shop_price),min(shop_price),avg(shop_price),sum(goods_number),count(*) FROM goods GROUP BY cat_id;

3. having 筛选数据

having是针对where条件结果进行筛选,是对内存数据操作,所以having必须用在where之后。

# ⑴ 查询该店的商品比市场价所节省的价格
SELECT goods_name,market_price-shop_price FROM goods;

# ⑵ 查询每个商品所积压的货款
SELECT goods_name,shop_price*goods_number FROM goods;

# ⑶ 查询该店积压的总货款
SELECT sum(shop_price*goods.goods_number) FROM goods;

# ⑷ 查询该店每个栏目下面积压的货款
SELECT cat_id,sum(shop_price*goods_number) FROM goods GROUP BY cat_id;

# ⑸ 查询比市场价省钱200元以上的商品及该商品所省的钱
SELECT goods_id,goods_name,(market_price-goods.shop_price) AS save FROM goods HAVING save>200;

# ⑹ 查询积压货款超过2W元的栏目,以及该栏目积压的货款
SELECT cat_id,sum(shop_price*goods.goods_number) AS catPrice FROM goods GROUP BY cat_id HAVING catPrice>20000;

# ⑺ 查询出2门及2门以上不及格者的平均成绩
  成绩表result数据如下:
  +------+---------+-------+
  | name | subject | score |
  | 张三 |  数学   |  90    |
  | 张三 |  语文   |  50    |
  | 张三 |  地理   |  40    |
  | 李四 |  语文   |  55    |
  | 李四 |  政治   |  45    |
  | 王五 |  政治   |  30    |
  +------+---------+-------+
  SELECT name,avg(score),sum(score<60) AS fail FROM result GROUP BY name HAVING fail>=2;

4. order by 排序和limit限制取出条目

当按某列排序(默认asc升序,desc降序)无法满足要求时,可以在列的内部再继续排序。实际使用中oder by经常和limit配合一起使用。 limit有两个参数,分别是limit 偏移量,取出条目,可以使用在分页上。

# (1)按价格由高到低排序
SELECT goods_id,goods_name,shop_price FROM goods ORDER BY shop_price ASC;

# (2)按发布时间由早到晚排序
SELECT goods_id,goods_name,shop_price FROM goods ORDER BY goods_id DESC;

# (3)接栏目由低到高排序,栏目内部按价格由高到低排序
SELECT cat_id,goods_name,shop_price FROM goods ORDER BY cat_id ASC, shop_price DESC;

# (4)取出价格最高的前三名商品
SELECT goods_id,goods_name,shop_price FROM goods ORDER BY shop_price DESC LIMIT 0,3;

# (5)取出点击量前三名到前5名的商品
SELECT goods_name,shop_price,click_count FROM goods ORDER BY click_count DESC LIMIT 0,5;

5. 子查询

(1) where子查询

内层select查询的结果充当外层select的where条件的查询。

# 取出每个栏目下最新的商品
SELECT cat_id,goods_id,goods_name,shop_price FROM goods WHERE goods_id IN (SELECT max(goods_id) FROM goods GROUP BY cat_id);

(2) from子查询

内层select作为一张表(AS table),外层select从内层表取出数据。

# 取出每个栏目下最新的商品
SELECT cat_id,goods_id,goods_name,shop_price FROM (SELECT * FROM goods ORDER BY cat_id ASC,goods_id DESC) AS tmp GROUP BY cat_id;

(3) exists子查询

exists指定一个子查询,检测行的存在。该子查询实际上并不返回任何数据,而是返回值True或False。exists子查询能完成的where子查询 in也能完成。

# 取出没有商品的栏目
SELECT * FROM category WHERE NOT exists(SELECT * FROM goods WHERE category.cat_id=goods.cat_id);

子查询练习

# 查询出最新一行商品
SELECT goods_id,goods_name,shop_price FROM goods WHERE goods_id=(SELECT max(goods_id) FROM goods);

# 查询出编号为19的商品的栏目名称(where和连接查询)
where子查询:
SELECT cat_id,cat_name FROM category WHERE cat_id=(SELECT cat_id FROM goods WHERE goods_id=19);
连接查询:
SELECT category.cat_id,category.cat_name FROM 
  category INNER JOIN goods ON category.cat_id=goods.cat_id 
WHERE goods.goods_id=19;

# 用where和from型子查询方式把每个栏目下面最新的商品取出来
where子查询:
SELECT goods_id,cat_id,goods_name FROM goods WHERE goods_id IN
(SELECT max(goods_id) FROM goods GROUP BY cat_id);
from子查询:
SELECT goods_id,cat_id,goods_name FROM 
(SELECT * FROM goods ORDER BY cat_id ASC,goods_id DESC) AS tmp GROUP BY tmp.cat_id;

# 用exists型子查询,查出所有有商品的栏目
SELECT * FROM category WHERE exists(SELECT * FROM goods WHERE category.cat_id=goods.cat_id);

6. join连接查询

(1) INNER JOIN内连接查询

把两张独立代表拼接成一张大表,拼接时指定匹配条件。

# 语法:1 INNER JOIN2 ON 匹配条件

# 把boy表和girl表同一组的人取出来
SELECT * FROM boy INNER JOIN girl ON boy.hid=girl.hid;

(2) LEFT JOIN左连接查询

以左边的表为标准,有匹配条件取出值来,没有则填充默认值。

# 以boy表为标准,把boy表和girl表进行同组匹配
SELECT * FROM boy LEFT JOIN girl ON boy.hid=girl.hid;

(3) RIGHT JOIN右连接查询

以右边的表为标准,有匹配条件取出值来,没有则填充默认值。

# 以girl表为标准,把boy表和girl表进行同组匹配
SELECT * FROM boy RIGHT JOIN girl ON boy.hid=girl.hid;

连接查询练习

# 取出所有商品的商品名,栏目名,价格
SELECT goods.goods_id,goods.goods_name,category.cat_name,goods.shop_price FROM goods LEFT JOIN category ON goods.cat_id=category.cat_id;

# 取出第4个栏目下的商品的商品名,栏目名,价格
SELECT goods.goods_id,goods.goods_name,category.cat_name,goods.shop_price FROM goods LEFT JOIN category ON goods.cat_id=category.cat_id WHERE goods.cat_id=4;

# 查出 2006-6-1 到2006-7-1之间举行的所有比赛,并且用以下形式列出:主队名  比分 客队 比赛时间
表名:m
+-----+------+------+------+------------+
| mid | hid  | gid  | mres | matime     |
+-----+------+------+------+------------+
|   1 |    1 |    2 | 2:0  | 2006-05-21 |
|   2 |    2 |    3 | 1:2  | 2006-06-21 |
|   3 |    3 |    1 | 2:5  | 2006-06-25 |
|   4 |    2 |    1 | 3:2  | 2006-07-21 |
+-----+------+------+------+------------+

队名:t
+------+----------+
| tid  | tname    |
+------+----------+
|    1 | 国安     |
|    2 | 申花     |
|    3 | 公益联队 |
+------+----------+

# 写法一:
SELECT ttb.tname,ttb.mres,t.tname,ttb.matime FROM (SELECT * FROM m LEFT JOIN t ON m.hid=t.tid)AS ttb LEFT JOIN t ON ttb.gid=t.tid WHERE ttb.matime BETWEEN '2006-06-01' AND '2006-07-01';

# 写法二:
SELECT t1.tname,mres,t2.tname,matime FROM m LEFT JOIN t AS t1 ON m.hid = t1.tid LEFT JOIN t AS t2 ON m.gid = t2.tid WHERE matime BETWEEN '2006-06-01' AND '2006-07-01';

7. union查询

把两条或多条sql查询的结果合并成一个结果集。主要用途:两张不同的表中有相同的列时,把结果集合并,或者简化两个复杂的where条件, 使用条件:两个表的列必须相同,但是例外的是列名称可以不相同。

注意事项:

  • 完全相等的行将会合并,合并是耗时的操作,一般不让union合并,使用union all则不合并。
  • union子句中一般不用order by,在union合并后可以再order by。
# (1) 合并表a和表b,不合并相同的行
SELECT * FROM a UNION ALL SELECT * FROM b;

# (2) 对两个表相同id的行进行num列求和。
SELECT tmp.id,sum(tmp.num) FROM
(SELECT * FROM a UNION ALL SELECT * FROM b) AS tmp
GROUP BY tmp.id;
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

攻城狮·建哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值