SQL数据查询(MySQL入门)

SQL数据查询(MySQL入门)

数据查询语言DQL也称为数据检索语句,是一种面向结构化数据的查询语言。用来在表中获取数据,确定数据怎样在应用程序给出,SQL数据查询包括单表查询和多表查询。



1. 引言

首先,回顾一下datetime数据类型,它的结构分别由year、month、day、time构成,datetime用来存储日期和时间。接下来我们就在user表中插入字段rgdata,datatime类型,非空约束。

mysql> alter table user add rgdate datetime not null;
Query OK, 0 rows affected
Records: 0  Duplicates: 0  Warnings: 0
mysql> desc user;
+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| uid       | int(20)     | NO   | PRI | 0       |       |
| name      | varchar(30) | NO   |     | NULL    |       |
| password  | varchar(30) | NO   |     | NULL    |       |
| birthday  | datetime    | NO   |     | NULL    |       |
| telephone | varchar(30) | NO   |     | NULL    |       |
| rgdate    | datetime    | NO   |     | NULL    |       |
+-----------+-------------+------+-----+---------+-------+
mysql> select * from user;
+-------+--------+----------+---------------------+-------------+---------------------+
| uid   | name   | password | birthday            | telephone   | rgdate              |
+-------+--------+----------+---------------------+-------------+---------------------+
| 10000 | 小文   | xiao123  | 1999-06-01 00:00:00 | 18866899966 | 2016-06-01 16:46:08 |
| 10001 | 张三   | z123456  | 1990-11-15 00:00:00 | 15286947945 | 2017-01-01 16:46:12 |
| 10002 | 李四   | lisi000  | 1989-08-24 00:00:00 | 19856245232 | 2017-04-01 16:46:15 |
| 10003 | 王麻子 | wangmazi | 1995-09-15 00:00:00 | 17932036662 | 2019-07-01 17:46:20 |
| 10004 | 大胖   | 6666666  | 1998-08-10 00:00:00 | 18782659898 | 2020-12-01 07:46:22 |
+-------+--------+----------+---------------------+-------------+---------------------+
mysql> select * from goods;
+-------+------+--------+-------+------+
| gid   | code | name   | price | city |
+-------+------+--------+-------+------+
| 20000 |  101 | 坚果   |   100 | 重庆 |
| 20001 |  102 | 汉服   |   200 | 上海 |
| 20002 |  103 | 空调   |  2000 | 深圳 |
| 20003 |  101 | 薯片   |   150 | 重庆 |
| 20004 |  102 | 羽绒服 |   300 | 浙江 |
| 20005 |  101 | 辣条   |    50 | 重庆 |
| 20006 |  103 | 冰箱   | NULL  | 深圳 |
+-------+------+--------+-------+------+
mysql> select * from goodstype;
+------+------+
| code | type |
+------+------+
|  101 | 零食 |
|  102 | 服装 |
|  103 | 电器 |
+------+------+
mysql> select * from orders;
+-------+-------+-------+----------+
| oid   | uid   | gid   | quantity |
+-------+-------+-------+----------+
| 30001 | 10002 | 20003 |      100 |
| 30002 | 10004 | 20000 |       10 |
| 30003 | 10002 | 20004 |        2 |
| 30004 | 10001 | 20005 |       20 |
| 30005 | 10003 | 20001 |        8 |
| 30006 | 10001 | 20002 |        1 |
| 30007 | 10002 | 20005 |       40 |
| 30008 | 10004 | 20001 |        2 |
| 30009 | 10000 | 20004 |        1 |
+-------+-------+-------+----------+

日期与时间类型,如下表:

类型格式字节数取值范围
yearyyyy11901~2155
timehh:mm:ss3-838:59:59~838:59:59
dateyyyy-mm-dd41000-01-01~9999-12-31
timestampyyyy-mm-dd hh:mm:ss419700101080001~20380119111407
datetimeyyyy-mm-dd hh:mm:ss81000-01-01 00:00:00~9999-12-31 23:59:59
注:使用current_timestamp获取系统当前日期时间,常用于默认时间设置。

2. 单表查询

2.1 比较运算符

查询user表中用户uid=10002的注册时间rgdate。

mysql> select rgdate from user where uid=10002;
+---------------------+
| rgdate              |
+---------------------+
| 2017-04-01 16:46:15 |
+---------------------+

查询user表中在2019年后注册的所有用户姓名name。

mysql> select name from user where year(rgdate)>=2019;
+--------+
| name   |
+--------+
| 王麻子 |
| 大胖   |
+--------+

2.2 逻辑运算符

查询goods表中生产城市在重庆和商品价格为100的商品名称name。

mysql> select name from goods where city='重庆' and price='100';
+------+
| name |
+------+
| 坚果 |
+------+

查询goods表中生产城市不在重庆的商品名称name。

mysql> select name from goods where not(city='重庆');
+--------+
| name   |
+--------+
| 汉服   |
| 空调   |
| 羽绒服 |
| 冰箱   |
+--------+

2.3 regexp关键字

MySQL支持正则表达式的匹配。正则表达式通常用来检索或替换符合某个模式的文本内容,根据指定的匹配模式匹配文本中符合要求的字符串。regexp常用字符匹配模式如下表:

正则表达式的模式字符说明示例
^匹配字符串的开始位置^d:如do,dog
$匹配字符串的结束位置t$:如cat,test
.匹配除“\n”之外的任意字符s.e:如she,see
[…]匹配字符集合中的任意一个字符[12]:如100,222
[^…]匹配非字符集合中的任意一个字符[^123]:如456,789
p1|p2|p3匹配p1或p2或p3good|bad:如good,bad
*匹配零个或多个在它前面的字符go*d:如bad,good,等价于{0,}
+匹配前面的字符1次或多次vi+d:如vid,vivid,等价于{1,}
{n}匹配前面的字符串至少n次,n为非负整数o{2}:如good,zoo
{n,m}匹配前面的字符串至少n次,至多m次,m和n均为非负整数,其中n<=mz{2,4}:如zz,zzzz
查询user表中在2017年注册,且电话尾号为5的用户姓名name,用户年龄age。
mysql> select name,year(now())-year(birthday) as age from user where year(rgdate)=2017 and telephone regexp '5$';
+------+-----+
| name | age |
+------+-----+
| 张三 |  32 |
+------+-----+

注:now( )函数返回当前的日期和时间,as子句用来给字段定义别名。


2.4 like关键字

查询user表中用户姓名为“张”开头的用户信息。

mysql> select * from user where name like '张%';
+-------+------+----------+---------------------+-------------+---------------------+
| uid   | name | password | birthday            | telephone   | rgdate              |
+-------+------+----------+---------------------+-------------+---------------------+
| 10001 | 张三 | z123456  | 1990-11-15 00:00:00 | 15286947945 | 2017-01-01 16:46:12 |
+-------+------+----------+---------------------+-------------+---------------------+

查询user表中用户姓名为“王”开头,“子”结尾的用户信息。

mysql> select * from user where name like '王_子';
+-------+--------+----------+---------------------+-------------+---------------------+
| uid   | name   | password | birthday            | telephone   | rgdate              |
+-------+--------+----------+---------------------+-------------+---------------------+
| 10003 | 王麻子 | wangmazi | 1995-09-15 00:00:00 | 17932036662 | 2019-07-01 17:46:20 |
+-------+--------+----------+---------------------+-------------+---------------------+

注:通配符%表示任意字符串,_表示任何单个字符;当like后的字符串不含通配符时,则可以用“=”运算符替代,而“<>”则可以替代not like运算。


2.5 in关键字

查询goods表中生产城市为重庆,上海的商品名称name。

mysql> select name from goods where city in('重庆','上海');
+------+
| name |
+------+
| 坚果 |
| 汉服 |
| 薯片 |
| 辣条 |
+------+

2.6 distinct关键字

查询goods表中商品价格大于等于100的商品在哪些城市。

mysql> select distinct city from goods where price>=100;
+------+
| city |
+------+
| 重庆 |
| 上海 |
| 深圳 |
| 浙江 |
+------+

注:当查询结果集的数据重复时,可使用distinct关键字去除重复的结果集。


2.7 is null关键字

查询goods表中商品价格为空的商品名称name。

mysql> select name from goods where price is null;
+------+
| name |
+------+
| 冰箱 |
+------+

2.8 between and关键字

查询goods表中商品价格为150到300之间的商品名称name。

mysql> select name from goods where price between 150 and 300;
+--------+
| name   |
+--------+
| 汉服   |
| 薯片   |
| 羽绒服 |
+--------+

2.9 limit子句

使用limit限制结果集返回的行数。

查询goods表中第3行开始的连续4行记录的商品gid,商品编码code,商品名称name。

mysql> select gid,code,name from goods limit 2,4;
+-------+------+--------+
| gid   | code | name   |
+-------+------+--------+
| 20002 |  103 | 空调   |
| 20003 |  101 | 薯片   |
| 20004 |  102 | 羽绒服 |
| 20005 |  101 | 辣条   |
+-------+------+--------+

注:limit子句来指定查询结果从哪一条记录开始以及一共查询多少行记录,格式为limit [offset,] nums。参数offset表示偏移量(初始位置),参数nums表示显示记录的条数,如果偏移量为0则从查询结果的第一条记录开始。


2.10 order by子句

order by子句可以对结构集进行升序(ASC)和降序(DESC)排列,默认为升序。

查询goods表中商品编码为101的商品gid,商品名称name以及商品价格price并按照价格升序排序。

mysql> select gid,name,price from goods where code=101 order by price;
+-------+------+-------+
| gid   | name | price |
+-------+------+-------+
| 20005 | 辣条 |    50 |
| 20000 | 坚果 |   100 |
| 20003 | 薯片 |   150 |
+-------+------+-------+

注:当指定的排序关键列有多个时,应分别指出各列的升序或降序选项。


2.11 group by子句

group by子句通常和聚合函数一起使用,才能实现对查询结果集进行分组和统计等操作。聚合函数有sum,avg,max,min,count,group_concat。

按照goods表中的生产城市进行分组查询。

mysql> select group_concat(name),city from goods group by city;
+--------------------+------+
| group_concat(name) | city |
+--------------------+------+
| 汉服               | 上海 |
| 羽绒服             | 浙江 |
| 空调,冰箱          | 深圳 |
| 坚果,薯片,辣条     | 重庆 |

查询每个生产城市的平均商品价格。

mysql> select avg(price) as 平均商品价格,city from goods
    -> group by city;
+--------------+------+
| 平均商品价格 | city |
+--------------+------+
| 200.0000     | 上海 |
| 300.0000     | 浙江 |
| 2000.0000    | 深圳 |
| 100.0000     | 重庆 |
+--------------+------+

查询goods表中生产城市来自于重庆和深圳的商品数量并进行汇总。

mysql> select city,count(*) as 商品数量 from goods
    -> where city in('重庆','深圳')
    -> group by city
    -> with rollup;
+------+----------+
| city | 商品数量 |
+------+----------+
| 深圳 |        2 |
| 重庆 |        3 |
| NULL |        5 |
+------+----------+

查询goods表中商量数量大于等于1的生产城市city。

mysql> select city,count(*) as 商品数量 from goods
    -> group by city
    -> having count(*)>=1;
+------+----------+
| city | 商品数量 |
+------+----------+
| 上海 |        1 |
| 浙江 |        1 |
| 深圳 |        2 |
| 重庆 |        3 |
+------+----------+

注:
a. group_concat( )函数必须跟group by子句一起使用;
b. group by和with rollup可以输出每一类分组的汇总值;
c. count(*)不需要任何参数,而且不能与distinct关键字一起使用;
d. having关键字和where关键字都用于设置条件表达式对查询结果集进行筛选,不同的是having关键字后可以使用聚合函数,而where关键字后不可以使用聚合函数。


3. 多表查询

多表查询包括连接查询(join),联合查询(union)以及子查询

3.1 连接查询(join)

3.1.1 内连接(inner join)

内连接又称为自然连接,自然连接也是除去重复属性的等值连接

查询商品类型为零食的商品gid,商品名称name,商品类型type以及价格price。

mysql> select gid,name,type,price
    -> from goodstype a join goods b
    -> on a.code=b.code
    -> where type='零食';
+-------+------+------+-------+
| gid   | name | type | price |
+-------+------+------+-------+
| 20000 | 坚果 | 零食 |   100 |
| 20003 | 薯片 | 零食 |   150 |
| 20005 | 辣条 | 零食 |    50 |
+-------+------+------+-------+
3 rows in set

查询李四购买的商品名称name,商品价格price,商品数量quantity。

mysql> select b.name,price,quantity
    -> from orders o join user u on o.uid=u.uid
    -> join goods b on o.gid=b.gid
    -> where u.name='李四';
+--------+-------+----------+
| name   | price | quantity |
+--------+-------+----------+
| 薯片   |   150 |      100 |
| 羽绒服 |   300 |        2 |
| 辣条   |    50 |       40 |
+--------+-------+----------+
mysql> select b.name,price,quantity
    -> from orders o join user u join goods b
    -> on o.uid=u.uid and o.gid=b.gid
    -> where u.name='李四';
+--------+-------+----------+
| name   | price | quantity |
+--------+-------+----------+
| 薯片   |   150 |      100 |
| 羽绒服 |   300 |        2 |
| 辣条   |    50 |       40 |
+--------+-------+----------+
mysql> select goods.name,price,quantity
    -> from orders join user using(uid)
    -> join goods using(gid)
    -> where user.name='李四';
+--------+-------+----------+
| name   | price | quantity |
+--------+-------+----------+
| 薯片   |   150 |      100 |
| 羽绒服 |   300 |        2 |
| 辣条   |    50 |       40 |
+--------+-------+----------+

注:这里a,b,o,u分别是指goodstype,goods,orders,user表的别名,使用表的别名是为了防止重名,以及有些数据库表名较长而且复杂,增加代码的可读性和可维护性;在join连接中,当连接条件由两张表相同名称且类型相同的字段相连时,可以使用using(列名)来连接。


3.1.2 外连接(outer join)

左外连接(left join),结果表中除了包括满足连接条件的行外,还包括左表的所有行;右外连接(right join),结果表中除了包括满足连接条件的行外,还包括右表的所有行。

使用left join查询用户uid=10002的订单总金额ototal。

mysql> select uid,sum(price*quantity) as ototal
    -> from orders o left join goods b
    -> on o.gid=b.gid
    -> where uid=10002;
+-------+--------+
| uid   | ototal |
+-------+--------+
| 10002 | 17600  |
+-------+--------+

使用right join查询每个用户的订单数量ordernum。

mysql> select u.uid,name,count(u.uid) as ordernum
    -> from user u right join orders o
    -> on u.uid=o.uid
    -> group by u.uid;
+-------+--------+----------+
| uid   | name   | ordernum |
+-------+--------+----------+
| 10000 | 小文   |        1 |
| 10001 | 张三   |        2 |
| 10002 | 李四   |        3 |
| 10003 | 王麻子 |        1 |
| 10004 | 大胖   |        2 |
+-------+--------+----------+

3.1.3 交叉连接(cross join)

交叉连接(cross join),交叉连接不带WHERE子句,它返回被连接的两个表所有数据行的笛卡尔积

使用cross join查询用户购买商品的所有可能情况。

mysql> select oid,gid,name from orders cross join user;

注:交叉连接无太多应用价值,但它可以用来为数据库生成测试数据。


3.2 联合查询(union)

使用union查询商品类型为零食和服装的商品gid,商品名称name,商品价格price,并按照商品价格升序排序,显示前4行记录。

mysql> select gid,name,price from goods join goodstype
    -> on goods.code=goodstype.code
    -> where type='零食'
    -> union
    -> select gid,name,price from goods join goodstype
    -> on goods.code=goodstype.code
    -> where type='服装'
    -> order by price
    -> limit 4;
+-------+------+-------+
| gid   | name | price |
+-------+------+-------+
| 20005 | 辣条 |    50 |
| 20000 | 坚果 |   100 |
| 20003 | 薯片 |   150 |
| 20001 | 汉服 |   200 |
+-------+------+-------+

注:join可以看作是将表进行水平组合,而union则是将表进行垂直组合。


3.3 子查询(嵌套查询)

  • 子查询是指在一个外层查询中包含有另一个内层查询,其中外层查询称为主查询,内层查询称为子查询。
  • 子查询中可能包括in,not in,any,some,all,exists和not exists等关键字,还可能包括比较运算符。
  • SQL允许多层嵌套,由内而外地进行分析,子查询的结果作为主查询的查询条件。
  • 子查询的结果集也可用于插入,修改和删除数据。
  • 通过子查询,实现多表之间的查询。
3.3.1 使用比较运算符的子查询

查询价格比汉服贵的商品名称name,商品价格price。

mysql> select name,price from goods where price>(select price from goods where name='汉服');
+--------+-------+
| name   | price |
+--------+-------+
| 空调   |  2000 |
| 羽绒服 |   300 |
+--------+-------+

注:子查询中一般不使用order by子句,只能对最终查询结果进行排序。


3.3.2 使用in关键字的子查询

查询已购物并且订单总金额大于等于1000的用户uid,用户名称name。

mysql> select uid,name from user
    -> where uid in (select uid from orders join goods using(gid) group by uid having sum(price*quantity)>1000);
+-------+--------+
| uid   | name   |
+-------+--------+
| 10001 | 张三   |
| 10002 | 李四   |
| 10003 | 王麻子 |
| 10004 | 大胖   |
+-------+--------+

注:int关键字同between and关键字一样用来限制查询数据的范围,not in关键字的作用与此相反。


3.3.3 使用any、some或all关键字的子查询

查询价格比服装类商品都低的商品gid,商品编码code,商品名称name和商品价格price。

mysql> select gid,code,name,price from goods
    -> where price<all(select price from goods where code=(select code from goodstype where type='服装'));
+-------+------+------+-------+
| gid   | code | name | price |
+-------+------+------+-------+
| 20000 |  101 | 坚果 |   100 |
| 20003 |  101 | 薯片 |   150 |
| 20005 |  101 | 辣条 |    50 |
+-------+------+------+-------+

注:all则表示外层查询的表达式要与子查询的结果集中的所有值匹配;any、some表示外层查询的表达式与子查询结果集中的值有一个匹配;any、some或all运算符必须与比较运算符一起使用。


3.3.4 使用exists关键字的子查询

如果user表中存在uid=10003的记录,则查询电话尾号为8的用户uid,用户姓名name,用户电话telephone。

mysql> select uid,name,telephone from user
    -> where telephone regexp '8$' and exists(select uid from user where uid=10003);
+-------+------+-------------+
| uid   | name | telephone   |
+-------+------+-------------+
| 10004 | 大胖 | 18782659898 |
+-------+------+-------------+

注:使用exists关键字的子查询不需要返回任何实际数据,而仅返回一个逻辑值。如果内层查询语句查询到满足条件的记录,就返回一个真值(true),并且外层查询语句将进行查询,否则就返回一个假值(false),外层查询语句不会进行查询。not exists关键字的作用与此相反。


——>以上内容是关于SQL数据查询的基础知识,希望对初学者或再次学习者有所帮助,基础打扎实,不怕风吹雨打! 如果以上内容有错误或者内容不全,望大家提出!我也会继续写好每一篇博文!

待续未完
——文优

欢迎观看和提问!!!

下一篇:SQL查询的优化(MySQL入门)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

文优

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

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

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

打赏作者

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

抵扣说明:

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

余额充值