MySQL之DQL数据查询操作
Posted 蚂蚁小哥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL之DQL数据查询操作相关的知识,希望对你有一定的参考价值。
一:SQL概述及规范
SQL(Structured Query Language,结构化查询语言)是使用关系模型的数据库应用语言,与数据直接打交道,由 IBM 上世纪70年代开发出来。后由美国国家标准局(ANSI)开始着手制定SQL标准,先后有SQL-86,SQL-89,SQL-92,SQL-99等标准。SQL有两个重要的标准,分别是SQL92 和SQL99,它们分别代表了 92 年和 99 年颁布的 SQL 标准,我们今天使用的 SQL 语言依然遵循这些标准。注:不同的数据库生产厂商都支持SQL语句,但都有特有内容(比如MySQL和Oracle的语法有一点小差异)
SQL有两个主要的标准,分别是 SQL92 和 SQL99 。92 和 99 代表了标准提出的时间,SQL92 就是 92 年提出的标准规范。当然除了 SQL92 和 SQL99 以外,还存在 SQL-86、SQL-89、SQL:2003、SQL:2008、SQL:2011 和 SQL:2016 等其他的标准。实际上最重要的 SQL 标准就是 SQL92 和 SQL99。一般来说 SQL92 的形式更简单,但是写的 SQL 语句会比较长,可读性较差。而 SQL99 相比于 SQL92 来说,语法更加复杂,但可读性更强。我们从这两个标准发布的页数也能看出,SQL92 的标准有 500 页,而 SQL99 标准超过了1000 页。实际上从 SQL99 之后,很少有人能掌握所有内容,因为确实太多了。就好比我们使用Windows、Linux 和 Office 的时候,很少有人能掌握全部内容一样。我们只需要掌握一些核心的功能,满足日常工作的需求即可。
SQL92 和 SQL99 是经典的 SQL 标准,也分别叫做 SQL-2 和 SQL-3 标准。也正是在这两个标准发布之后,SQL影响力越来越大,甚至超越了数据库领域。现如今 SQL 已经不仅仅是数据库领域的主流语言,还是信息领域中信息处理的主流语言。在图形检索、图像检索以及语音检索中都能看到 SQL 语言的使用。
1:SQL分类
SQL语句的五种分类分别是DQL、DML、DDL、TCL和TCL,下面对SQL语句的五种分类进行列
①:DDL(Data Definition Languages、数据定义语言)
数据定义语言DDL用来创建数据库中的各种对象,创建、删除、修改表的结构,比如表、视图、索引、同义词、聚簇等,简称DDL。和DML相比,
DML是修改数据库表中的数据,而DDL是修改数据中表的结构。
主要的语句关键字包括:CREATE、DROP、ALTER 等
②:DML(Data Manipulation Language、数据操作语言)
用户通过它可以实现对数据库中表里面的数据进行的基本操作。用于添加、删除、更新和查询数据库记录,并检查数据完整性。
主要的语句关键字包括 INSERT、DELETE、UPDATE 等
③:DQL(Data Query Language、数据库查询语言)
基本结构是由SELECT子句,FROM子句,WHERE子句组成的查询块,用来查询需要获取的数据
主要的语句关键字包括 SELECT
③:DCL(Data Control Language、数据控制语言)
用来定义数据库、表、字段、用户的某种特权和安全级别;还可以控制数据库操纵事务发生的时间及效果,对数据库实行监视等。
主要的语句关键字包括 GRANT 、 REVOKE 、SAVEPOINT 等
⑤、TCL(事务控制语言、Trasactional Control Languag)
TCL经常被用于快速原型开发、脚本编程、GUI和测试等方面(用来事务控制)
主要的语句关键字包括 COMMIT、ROLLBACK
注:TCL也可以归为到DCL中,为了细分才拆分;DQL也可以归为到DML中,因为查询的频繁被单独从DML摘出来
2:SQL语言的基本规范
1:基本规范
①:SQL可以写在一行或者多行。为了提高可读性,各子句分行写,必要时使用缩进
②:每条命令可以使用 ; 或 \\g 或 \\G 结束
③:关键字不能被缩写也不能分行
④:必须保证所有的()、单引号、双引号是成对结束的
⑤:必须使用英文状态下的半角输入方式
⑥:字符串型和日期时间类型的数据尽量使用单引号(\' \')表示
⑦:列的别名,尽量使用双引号(" "),而且不建议省略 as
⑧:若语句写错了或不想执行本次语句,则需要在语句最后面输入 \\c 代表放弃这个语句的执行
2:大小写规范
①:MySQL 在 Windows 环境下是大小写不敏感的
②:MySQL 在 Linux 环境下是大小写敏感的
数据库名、表名、表的别名、变量名是严格区分大小写的
关键字、函数名、列名(字段名)、列的别名(字段的别名) 是忽略大小写的
③:推荐采用统一的书写规范
数据库名、表名、表别名、字段名、字段别名等都小写
SQL 关键字、函数名、绑定变量等都大写
3:注释
单行注释:# 注释文字(MySQL特有的方式)
单行注释:-- 注释文字(-- 后面必须包含一个空格。)
多行注释:/* 注释文字 */
4:基本命名规则
①:数据库、表名不得超过30个字符,变量名限制为29个
②:命名时只能包含 A–Z, a–z, 0–9, _ 共63个字符
③:数据库名、表名、字段名等对象名中间不要包含空格
④:同一个MySQL软件中,数据库不能同名;同一个库中,表不能重名;同一个表中,字段不能重名
⑤:必须保证你的字段没有和保留字、数据库系统或常用方法冲突。
如果坚持使用,请在SQL语句中使用 ``(着重号)引起来;如 `demo_table`
⑥:保持字段名和类型的一致性,在命名字段并为其指定数据类型的时候一定要保证一致性。
假如数据类型在一个表里是整数,那在另一个表里可就别变成字符型了
后面后针对这些规范执行,也会再后面强调重要规范
基础资料:MySQL运算符介绍
二:DQL基础语法
基本语法:SELECT 查询的字段 FROM 表名;
①:查询出来的结果集数据都是放在一个虚拟的表展示; ②:SELECT 查询列表类似 java 的打印语句 SELECT 后根的查询列表可以由多个组成,中间使用逗号隔开 如:SELECT 字段1 , 字段2 , 字段3 ... FROM 表名;
问:查询student表中的sname、sage、saddress字段
答:SELECT sname,sage,ssex,saddress FROM student;
SQL执行顺序:
SELECT sname,sage,ssex,saddress FROM student;
基本语句执行顺序是先看后面 FROM 是否可以找到此表,找到再执行 SELECT 查询
# ①:from student
# ②:select sname,sage,saddress
Ⅰ:查询列表可以是字段、表达式、常量、函数等
查询常量:select 100 from dual; 查询表达式:select 12%5; 查询单个字段:select sname from student 查询多个字段:select sname , saddress from student; 查询所有字段:select * from student; -- 一般不推荐使用 查询函数当前使用的数据库:select database(); 查询函数当前数据库版本:select version(); 查询函数当前数据库使用者:select user();
注:一般情况下,除非需要使用表中所有的字段数据,最好不要使用通配符‘*’。使用通配符虽然可以节省输入查询语句的时间,但是
获取不需要的列数据通常会降低查询和所使用的应用程序的效率。通配符的优势是,当不知道所需要的列的名称时,可以通过它获
取它们。在生产环境下,不推荐你直接使用 SELECT * 进行查询。
注:在没有 FROM 后面的表时也可以使用 DUAL 代替,代表不用查找具体的数据库表了
如:select 100+1 from dual (切记这样的使用dual则不能再查询 * )
Ⅱ:起别名
select sname as 姓名 from student; select sname as "姓名" from student; select sname as "姓 名" from student; select sname 姓名 from student; 说明:使用别名可用 AS 关键字或者空格隔开,也可以用引号把别名引起来,当别名中间有空格就必须用引号引起来 注:议别名简短,见名知意;列名和别名之间加入关键字AS,别名使用双引号,
Ⅲ:MySQL中的加号 “+” 的使用
①:加法运算 前提2个操作数都是数值 select 100+200;==> 300 ②:其中一个操作数为字符型,将字符型数据强制转换成数值型,如果无法转换,则直接当做 0 处理 select \'hello\'+100; ==> 0+100 ==> 100
注:按照Java中的语法应该为 hello100 但是SQL却不同,要想拼接则使用 CONCAT(value,value,...)函数 ④:其中一个操作数为null和任何数相加都为null select null+100; ==> null
Ⅳ:去重查询 DISTINCT
查询数据库student学生表所有学生的年龄 select distinct sage from student; + | sage | + | 21 | | 23 | | 24 | | 25 | | 22 | + 5 rows in set (0.00 sec)
Ⅴ:扩展使用 CONCAT()拼接函数
使用拼接函数:select concat( \'值\' ,\'值\' , ...); 注:如果一旦里面的值有一个为null,从而所有的都变成null select concat(\'博客园\',\'蚂蚁小哥\') AS "打 印"; + | 打 印 | + | 博客园蚂蚁小哥 | + 1 row in set (0.00 sec) 举例存在NULL的值拼接(因为null写不出来,所以我通过表查询出来) select sid,sname,saddress from student where saddress is null; + | sid | sname | saddress | + | 20 | 周迟蒲 | NULL | | 48 | 张桥共 | NULL | + select concat(sname,\' --- \',saddress) from student where sid = \'20\'; + | concat(sname,\' --- \',saddress) | + | NULL | +
Ⅵ:扩展使用 IFNULL(value1,value2);
判断 值1 如果为空就显示 值2 反之显示 值1 select concat(sname, \'---\',ifnull(saddress , \'地址为空\')) as "显示" from student where sid = 20; + | 显示 | + | 周迟蒲 + select ifnull(null,\'空\') + | ifnull(null,\'空\') | + | 空 | +
Ⅶ:查询表结构的几种方式
desc 表名; describe 表名; show columns from 表名; show create table 表名; mysql> desc student; + | Field | Type | Null | Key | Default | Extra | + | sid | int(11) | NO | PRI | NULL | auto_increment | | sname | varchar(5) | NO | | NULL | | | ssex | enum(\'男\',\'女\') | YES | | 男 | | | sage | tinyint(11) unsigned | NO | | 20 | | | scredit | double(3,1) | YES | | 60.0 | | | smoney | decimal(4,1) | YES | | 0.0 | | | saddress | varchar(10) | YES | | NULL | | | senrol | date | YES | | 2020-12-12 | | | fid | int(11) | YES | MUL | NULL | | | tid | int(11) | YES | MUL | NULL | | + Field:表示字段名称。 Type:表示字段类型, Null:表示该列是否可以存储NULL值。 Key:表示该列是否已编制索引。 PRI表示该列是表主键的一部分; UNI表示该列是UNIQUE索引的一部分; MUL表示在列中某个给定值允许出现多次。 Default:表示该列是否有默认值,如果有,那么值是多少。 Extra:表示可以获取的与给定列有关的附加信息,例如 AUTO_INCREMENT 等。
Ⅷ:着重号
我们需要保证表中的字段、表名等没有和保留字、数据库系统或常用方法冲突。
如果真的相同,请在SQL语句中使用一对``(着重号)引起来。如下面SQL中的order表和MySQL的排序关键字冲突 如:select * from `order`
Ⅸ:总结
三:条件查询 WHERE
基本语法:
SELECT 查询的字段 FROM 表名 WHERE 筛选条件
问:查询student表中的sname、sage、saddress字段;并且为男生 答:SELECT sname,sage,ssex,saddress FROM student where ssex = \'男\'; SQL执行顺序 # ①:执行 from 查找表 # ②:执行 where 筛选数据 # ③:执行 select 查询指定字段展示到虚拟表
四:查询并排序 ORDER BY
基本语法:
SELECT 查询的字段 FROM 表名 WHERE 筛选条件 ORDER BY 排序字段 [ASC(默认)/DESC]
注:如果没有使用排序操作,默认情况下查询返回的数据是按照添加数据的顺序显示的;可使用别名代替排序字段名
ASC:【ascend/升序】 DESC:【descend/降序】
单列排序:
问:查询学生表中姓名、年龄、学分、零花钱这四个字段,学分从高到底(降序)排序
SELECT sname,sage,scredit,smoney from student ORDER BY scredit DESC
问:查询学生表中姓名、年龄、学分、零花钱这四个字段,学分从低到高(升序)排序
SELECT sname,sage,scredit,smoney from student ORDER BY scredit
多列排序:
问:查询学生表中姓名、年龄、学分、零花钱这四个字段,年龄从高到底(降序)排序,并且学分从低到高(升序)排序
SELECT sname,sage,scredit,smoney from student ORDER BY sage DESC , scredit
SQL执行顺序:
执行顺序
1. 执行from 查询表是否存在
2. 执行where 筛选符合条件的数据
3. 执行select 查询指定字段展示到虚拟表
4. 执行order by 对指定的字段进行排序
注:可以使用不在SELECT列表中的列排序。在对多列进行排序的时候,首先排序的第一列必须有相同的列值,才会对第二列进行排序。如果第一列数据中所有值都是唯一的,将不再对第二列进行排序。
五:查询并分页 LIMIT n,m
基本语法
SELECT 查询的字段 FROM 表名 WHERE 筛选条件 LIMIT 【位置偏移量,】显示的条目数
查询返回的记录太多了,查看起来很不方便,所以LIMIT可以对数据进行分页显示;所谓分页显示,就是将数据库中的结果集,一段一段显示出来需要的条件。
分页查询:
问:查询学生表中前10条数据
SELECT * FROM student LIMIT 0,10 或者 SELECT * FROM student LIMIT 10
问:查询学生表中11条到20条数据
SELECT * FROM student LIMIT 10,10
问:查询学生表中21条到30条数据
SELECT * FROM student LIMIT 20,10
规律:分页显式公式:(当前页数-1)*每页条数,每页条数
SELECT * FROM table LIMIT(PageNo - 1)*PageSize,PageSize;
注意:LIMIT 子句必须放在整个SELECT语句的最后!
MySQL 8.0中可以使用“LIMIT 3 OFFSET 4”,意思是获取从第5条记录开始后面的3条记录,和“LIMIT 4,3;”返回的结果相同。
SELECT * FROM student LIMIT 3 OFFSET 4
mysql> SELECT * FROM student LIMIT 3 OFFSET 4;
+-----+-----------+------+------+---------+--------+--------------+------------+------+------+
| sid | sname | ssex | sage | scredit | smoney | saddress | senrol | fid | tid |
+-----+-----------+------+------+---------+--------+--------------+------------+------+------+
| 5 | 钱勤堃 | 女 | 23 | 8.0 | 101.7 | 安徽合肥 | 2018-01-05 | 5 | 1 |
| 6 | 潘恩依 | 女 | 24 | 22.0 | 967.7 | 安徽合肥 | 2018-11-18 | 6 | 4 |
| 7 | 陈国柏 | 女 | 24 | 10.0 | 697.5 | 安徽六安 | 2018-10-12 | 7 | 2 |
+-----+-----------+------+------+---------+--------+--------------+------------+------+------+
指定条目数查询:
问:查询学生表中查询出来的三条记录
SELECT * FROM student LIMIT 3
使用分页优点:约束返回结果的数量可以减少数据表的网络传输量 ,也可以提升查询效率 。如果我们知道返回结果只有1条,就可以使用 LIMIT 1 ,告诉 SELECT 语句只需要返回一条记录即可。这样的好处就是 SELECT 不需要扫描完整的表,只需要检索到一条符合条件的记录即可返回。
六:多表查询
多表查询也称为关联查询,指两个或者更多的表一起完成查询操作;不过这些能关联查询的表是有一些联系的(一对多,一对一);它们之间是一定有关联字段,这个关联字段可能建立了外键,也可能没有建立外键。
1:一对一、一对多、多对多概念
我就以博文开头的SQL建表语句资料进行一个说明这几个概念
一对一:表中的某一列对应着另外一张表中的某一列(A表有10条数据,关联对应的B表也会有10条数据)
这种一一对应的关系并不常见。一一对应的列可以放在一个表里面,其实这样做一定有原因,例如,把一张有50个字段的大表分成若干小表,
可以确保安全,防止信息泄露、防止单表数据量过大影响查询效率。
比如学生表和家庭表的关系(这里我们就考虑一个学生只有一个家庭,一个家庭只有一个孩子的情况),对于每个学生的家庭信息是
一个敏感信息,敏感信息除了统计学生家庭的管理员可以看到之外,其他人不能看到,这时家庭这些列数据经常被放在一个单独的表里面。
一对多:一张表中的一行数据对应另外表中的多行数据
这种关系在关系型列表中最常见。比如按照我上面的示例来说,一个老师表(辅导员)对应着多个学生数据信息(一个辅导员多个学生)
多对一:表中的多列对应另外表中的多列
可以将多对多关系视为通过中间表连接的两个一对多关系。中间表通常称为“连接表” 也称为“交叉引用表”。该表用于将其他两个表连接在一起
比如说一个学生可以报多个社团,一个社团同时也可以被多个学生报名,这就是一个多对多关系,说白了就是两个一对多,不过多对多需要
一个连接表来进行两个表的关联
2:多表连接及笛卡尔积(或交叉连接)理解
案例:查询辅导员信息和对应的学生信息
SELECT t.tid, t.tname, s.sid, s.sname FROM teacher t, student s
执行完我们会发现,出现了很多条数据,就是奇怪,先说一下,这个是因为没有连接条件导致的笛卡尔积错误,笛卡尔积查出的数据是连接表的乘积,
就比如teacher表4条数据,student表65条数据,那么上面的SQL查询出来260条数据
笛卡尔积(或交叉连接)的理解:
笛卡尔乘积是一个数学运算。假设我有两个集合 X 和 Y,那么 X 和 Y 的笛卡尔积就是 X 和 Y 的所有可能组合,也就是第一个对象来自于 X,
第二个对象来自于 Y 的所有可能。组合的个数即为两个集合中元素个数的乘积数。
SQL92中,笛卡尔积也称为交叉连接,英文是CROSS JOIN
SQL99中,使用CROSS JOIN关键字表示交叉连接。它的作用就是可以把任意表进行连接,即使这两张表不相关。
在MySQL中如下情况会出现笛卡尔积:
-- SQL92语法造成交叉连接
SELECT t.tid, t.tname, s.sid, s.sname FROM teacher t, student s
-- SQL99语法造成交叉连接
SELECT t.tid, t.tname, s.sid, s.sname FROM teacher t CROSS JOIN student s 交叉连接写法
SELECT t.tid, t.tname, s.sid, s.sname FROM teacher t INNER JOIN student s 内连接没有on连接条件
SELECT t.tid, t.tname, s.sid, s.sname FROM teacher t JOIN student s 内连接没有on连接条件
笛卡尔积的错误会在下面条件下产生:
①:省略多个表的连接条件(或关联条件)
②:连接条件(或关联条件)无效
③:所有表中的所有行互相连接
为了避免笛卡尔积, 可以在 WHERE 加入有效的连接条件。
加入连接条件后,查询语法:
SELECT table1.column, table2.column FROM table1, table2 WHERE table1.column1 = table2.column2; #连接条件
在WHERE子句中写入连接条件即可
-- SQL92语法解决交叉连接(笛卡尔积)
SELECT t.tid, t.tname, s.sid, s.sname FROM teacher t, student s WHERE t.tid = s.sid
-- SQL99语法解决交叉连接(笛卡尔积)
SELECT t.tid, t.tname, s.sid, s.sname FROM teacher t CROSS JOIN student s USING(tid)
SELECT t.tid, t.tname, s.sid, s.sname FROM teacher t INNER JOIN student s ON t.tid = s.tid
SELECT t.tid, t.tname, s.sid, s.sname FROM teacher t JOIN student s USING(tid)
这里的每个表名我使用了别名方式,所以只能使用别名的方式来点出指定的属性
多表连接(查询当前辅导员的学生和学生的家庭信息) SELECT t.tid, t.tname, s.sid, s.sname, f.fguardian,ftel FROM teacher t, student s, family f WHERE t.tid = s.tid AND s.fid = f.fid SELECT t.tid, t.tname, s.sid, s.sname, f.fguardian,ftel FROM teacher t INNER JOIN student s ON t.tid = s.tid INNER JOIN family f ON s.fid = f.fid
3:多表查询(等值连接&非等值连接)
等值连接: SELECT t.tid, t.tname, s.sid, s.sname FROM teacher t, student s WHERE t.tid = s.tid SELECT t.tid, t.tname, s.sid, s.sname FROM teacher t INNER JOIN student s ON t.tid = s.tid 非等值连接: 非等值连接就是两种或者两张以上的表之间没有一个指定的连接字段,其实非等值连接可以做等级评定 SELECT t.tid, t.tname, s.sid, s.sname, s.smoney, m.`level` FROM teacher t,student s,money_grades m WHERE t.tid = s.tid AND s.smoney BETWEEN m.highest AND m.lowest SELECT t.tid, t.tname, s.sid, s.sname, s.smoney, m.`level` FROM teacher t INNER JOIN student s ON t.tid = s.tid INNER JOIN money_grades m WHERE s.smoney BETWEEN m.highest AND m.lowest
4:多表查询(自连接&非自连接)
CREATE TABLE `tabbar` ( `id` int(11) NOT NULL PRIMARY KEY COMMENT \'主键ID\', `tab_name` varchar(10) DEFAULT NULL COMMENT \'导航标签名称\', `parent_id` int(11) DEFAULT NULL COMMENT \'父级导航名称\' ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `tabbar` (`id`, `tab_name`, `parent_id`) VALUES (1, \'游戏模块\', NULL),(2, \'英雄联盟\', 1),(3, \'穿越火线\', 1), (4, \'体育模块\', NULL),(5, \'排球比赛\', 4),(6, \'篮球比赛\', 4);
非自连接:上面的案例多表连接都是非自连接(多张不同的表进行连接) 自连接:当表a和表b本质上是同一张表,只是用区别名的方式虚拟出来两张表进行一个连接 查询tabbar表中的标签名称和父类的标签名称 select a.tab_name , b.tab_name from tabbar a, tabbar b WHERE a.id = b.parent_id select a.tab_name , b.tab_name from tabbar a RIGHT JOIN tabbar b ON a.id = b.parent_id select a.tab_name , b.tab_name from tabbar a INNER JOIN tabbar b ON a.id = b.parent_id
5:多表查询(内连接&外连接)
内连接: 合并具有同一列的两个以上的表的行, 结果集中不包含一个表与另一个表不匹配的行 SELECT t.tid, t.tname, s.sid, s.sname FROM teacher t, student s WHERE t.tid = s.tid SELECT t.tid, t.tname, s.sid, s.sname FROM teacher t INNER JOIN student s ON t.tid = s.tid 外连接: 两个表在连接过程中除了返回满足连接条件的行以外还返回左(或右)表中不满足条件的行,这种连接称为左(或右)外连接。 没有匹配的行时, 结果表中相应的列为空(NULL)。 说明:外连接分为左外连接、右外连接、全外连接(满外连接) 如果是左外连接,则连接条件中左边的表也称为主表,右边的表称为从表。 如果是右外连接,则连接条件中右边的表也称为主表,左边的表称为从表。 在SQL92中只有左右连接,没有全外连接(满外连接) SELECT s.sname, s.saddress, f.fguardian, f.ftel FROM student s, family f WHERE s.fid(+) = f.fid 左连接 SELECT s.sname, s.saddress, f.fguardian, f.ftel FROM student s, family f WHERE s.fid(+) = f.fid 右连接 注:上面两种方式在MySQL下是不支持92语法的 (+) 来实现左右连接,只可以内连接(Oracle支持) LEFT OUTER JOIN、LEFT JOIN(左外连接) RIGHT OUTER JOIN、RIGHT JOIN(右外连接) FULL OUTER JOIN、FULL JOIN(全外连接、满外连接)注:MySQL不支持这种全外连接 SELECT s.sname, s.saddress, f.fguardian, f.ftel FROM student s LEFT JOIN family f ON s.fid = f.fid 左外 SELECT s.sname, s.saddress, f.fguardian, f.ftel FROM student s RIGHT JOIN family f ON s.fid = f.fid 右外
补充:全外连接(满外连接)
全外连接的结果 = 左右表匹配的数据 + 左表没有匹配到的数据 + 右表没有匹配到的数据。SQL99是支持满外连接的。使用FULL JOIN 或 FULL OUTER JOIN来实现。需要注意的是,MySQL不支持FULL JOIN,但是可以用 LEFT JOIN UNION RIGHT join代替。
6:合并查询UNION的使用
合并查询结果利用UNION关键字,可以将SELECT语句查询出的多条结果进行一个结果组合变成单个结果集。注:多个SELECT查询出的结果合并时,列数、类型必须相同,并且相互对应;字段名称也尽量保持一致,因为字段名称取的是第一个SELECT查询出的结果的列名。各个SELECT语句之间使用UNION或UNION ALL关键字分隔。
基本语法:
SELECT column,... FROM table1 UNION [ALL] SELECT column,... FROM table2
UNION:操作符返回两个查询的结果集的并集,去除重复记录。
UNION ALL:操作符返回两个查询的结果集的并集。对于两个结果集的重复部分,不去重。
注:执行UNION ALL语句时所需要的资源比UNION语句少。如果明确知道合并数据后的结果数据不存在重复数据,或者不需要去除重复的数据,则尽量使用UNION ALL语句,以提高数据查询的效率。
举例:查询学生数据中性别男的一批数据在前面,性别女的一批数据在后面,并进行年龄降序排列 (SELECT * FROM student where ssex = \'男\' ORDER BY sage DESC) UNION ALL (SELECT * FROM student where ssex = \'女\' ORDER BY sage DESC)
7:使用MySQL中SQL99语法完成7种SQL JOINS连接
通过上面我们可以知道,在SQL92中只有内连接 ,但是在SQL99中有7种连接分别如下介绍的,但是MySQL支持的SQL92只有内连接和左右连接,其它的连接则我们需要使用特殊手段进行处理,下面则进行说明
七种连接方式实现: ①:内连接 INNER JOIN (MySQL支持 也叫自然连接同时也叫全等连接,即左边表和右边表共有数据的查询) 学生表和家庭表进行一个内连接,保证学生数据和家庭数据进行一一匹配,不符合则被筛除 SELECT s.sname, s.saddress, f.fguardian, f.ftel FROM student s INNER JOIN family f ON s.fid = f.fid ②:左(外)连接 LEFT JOIN (MySQL99支持 即查询左边表的独有数据) 学生表和家庭表进行一个左连接,保证学生数据不遗漏,无法匹配的学生数据的家庭则位null SELECT s.sname, s.saddress, f.fguardian, f.ftel FROM student s LEFT JOIN family f ON s.fid = f.fid ③:右(外)连接 RIGHT JOIN (MySQL99支持 即查询右边表的独有数据) 学生表和家庭表进行一个左连接,保证家庭数据不遗漏,无法匹配的家庭数据的学生则位null SELECT s.sname, s.saddress, f.fguardian, f.ftel FROM student s RIGHT JOIN family f ON s.fid = f.fid ④:其它连接 (A独有且无法与B关联的数据) 查找左表独有部分,则需查找左表和右表的共有部分并加上左表的独有部分,再将左表和右表的共有部分剔除即可 (也就是挑选右的主键为空的数据) SELECT s.sname, s.saddress, f.fguardian, f.ftel FROM student s LEFT JOIN family f ON s.fid = f.fid WHERE f.fid IS NULL ⑤:其它连接 (B独有且无法与A关联的数据) 查找右表独有部分,则需查找右表和左表的共有部分并加上右表的独有部分,再将右表和左表的共有部分剔除即可 (也就是挑选左的主键为空的数据) SELECT s.sname, s.saddress, f.fguardian, f.ftel FROM student s RIGHT JOIN family f ON s.fid = f.fid WHERE s.sid IS NULL; ⑥:全连接(满外连接) FULL OUTER JOIN (MySQL不支持) 表示将左表和右表的公共部分及左表、右表的独有部分,所有数据都查询出来 全连接 FULL OUTER JOIN 在MySQL语法报错!但是可以通过UNION关键字进行查询。UNION会把重复的行去掉,返回的行都是唯一的。 如果想保留重复行,可以使用UNION ALL关键字。 UNION其实就是将左表和右表的共有部分和左表的独有部分(即左连接LEFT JOIN),加上右表的独有部分(即右连接RIGHT JOIN) 合并起来,并进行去重即可。 (SELECT s.sname, s.saddress, f.fguardian, f.ftel FROM student s LEFT JOIN family f ON s.fid = f.fid) UNION (SELECT s.sname, s.saddress, f.fguardian, f.ftel FROM student s RIGHT JOIN family f ON s.fid = f.fid); 这种方式就是方式②和方式⑤结合,或者方式③和方式④结合;这里我就以方式②和方式⑤结合 (SELECT s.sname, s.saddress, f.fguardian, f.ftel FROM student s LEFT JOIN family f ON s.fid = f.fid) UNION ALL (SELECT s.sname, s.saddress, f.fguardian, f.ftel FROM student s RIGHT JOIN family f ON s.fid = f.fid WHERE s.sid IS NULL); ⑦:其它连接 (A独有且无法与B关联的数据和B独有且无法与A关联的数据) 查询左表独有部分并加上右表独有部分;实际就是方式④和方式⑤结合,并使用UNION或者UNION ALL进行连接即可。 (SELECT s.sname, s.saddress, f.fguardian, f.ftel FROM student s LEFT JOIN family f ON s.fid = f.fid WHERE f.fid IS NULL) UNION ALL (SELECT s.sname, s.saddress, f.fguardian, f.ftel FROM student s RIGHT JOIN family f ON s.fid = f.fid WHERE s.sid IS NULL);
8:SQL99语法新特性之自然连接
SQL99 在 SQL92 的基础上提供了一些特殊语法,比如 NATURAL JOIN 用来表示自然连接。我们可以把自然连接理解为 SQL92 中的等值连接。它会帮你自动查询两张连接表中所有相同的字段,然后进行等值连接。
在SQL92中使用: SELECT a.字段1, b.字段1, ... FROM 表A a, 表B b ON a.字段2 = b.字段2 AND a.字段3 = b.字段3 在SQL99中使用: SELECT a.字段1, b.字段1, ... FROM 表A a NATURAL JOIN 表B b
9:SQL99语法新特性之USING连接
当我们进行连接的时候,SQL99还支持使用 USING 指定数据表里的同名字段进行等值连接。但是只能配合JOIN一起使用。比如: 原始: SELECT t.tid, t.tname, s.sid, s.sname FROM teacher t INNER JOIN student s ON t.tid = s.tid 优化(tid为左表和右表相同字段): SELECT t.tid, t.tname, s.sid, s.sname FROM teacher t INNER JOIN student s USING(tid)
10:多表查询总结
表连接的约束条件可以有三种方式:WHERE, ON, USING
WHERE:适用于所有关联查询
ON:只能和JOIN一起使用,只能写关联条件。虽然关联条件可以并到WHERE中和其他条件一起写,但分开写可读性更好。
USING:只能和JOIN一起使用,而且要求两个关联字段在关联表中名称一致,而且只能表示关联字段值相等
注:我们要控制连接表的数量。多表连接就相当于嵌套 for 循环一样,非常消耗资源,会让 SQL 查询性能下降得很严重,因此不要连接不必要的表。在许多 DBMS 中,也都会有最大连接表的限制
11:基本多表查询案例(结合上方的7种SQL连接)
CREATE TABLE `t_dept`( `id` INT ( 11 ) NOT NULL AUTO_INCREMENT, `deptName` VARCHAR(30) DEFAULT NULL, `address` VARCHAR(40) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE = INNODB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8; CREATE TABLE `t_emp`( `id` INT ( 11 ) NOT NULL AUTO_INCREMENT, `name` VARCHAR(20) DEFAULT NULL, `age` INT ( 3 ) DEFAULT NULL, `deptId` INT ( 11 ) DEFAULT NULL, empno INT NOT NULL, PRIMARY KEY (`id`), KEY `idx_dept_id` ( `deptId` ) ) ENGINE = INNODB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8; INSERT INTO t_dept(deptName,address) VALUES(\'华山\',\'华山\'); INSERT INTO t_dept(deptName,address) VALUES(\'丐帮\',\'洛阳\'); INSERT INTO t_dept(deptName,address) VALUES(\'峨眉\',\'峨眉山\'); INSERT INTO t_dept(deptName,address) VALUES(\'武当\',\'武当山\'); INSERT INTO t_dept(deptName,address) VALUES(\'明教\',\'光明顶\'); INSERT INTO t_dept(deptName,address) VALUES(\'少林\',\'少林寺\'); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES(\'风清扬\',90,1,100001); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES(\'岳不群\',50,1,100002); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES(\'令狐冲\',24,1,100003); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES(\'洪七公\',70,2,100004); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES(\'乔峰\',35,2,100005); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES(\'灭绝师太\',70,3,100006); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES(\'周芷若\',20,3,100007); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES(\'张三丰\',100,4,100008); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES(\'张无忌\',25,5,100009); INSERT INTO t_emp(NAME,age,deptId,empno) VALUES(\'韦小宝\',18,null,100010);
SELECT d.deptName ,d.address ,e.name,e.age FROM t_dept d INNER JOIN t_emp e ON d.id = e.deptId SELECT d.deptName ,d.address ,e.name,e.age FROM t_dept d RIGHT JOIN t_emp e ON d.id = e.deptId SELECT d.deptName ,d.address ,e.name,e.age FROM t_dept d LEFT JOIN t_emp e ON d.id = e.deptId SELECT d.deptName ,d.address ,e.name,e.age FROM t_dept d RIGHT JOIN t_emp e ON d.id = e.deptId WHERE d.id IS NULL SELECT d.deptName ,d.address ,e.name,e.age FROM t_dept d LEFT JOIN t_emp e ON d.id = e.deptId WHERE e.id IS NULL (SELECT d.deptName ,d.address ,e.name,e.age FROM t_dept d RIGHT JOIN t_emp e ON d.id = e.deptId) UNION (SELECT d.deptName ,d.address ,e.name,e.age FROM t_dept d LEFT JOIN t_emp e ON d.id = e.deptId) (SELECT d.deptName ,d.address ,e.name,e.age FROM t_dept d RIGHT JOIN t_emp e ON d.id = e.deptId WHERE d.id IS NULL) UNION ALL (SELECT d.deptName ,d.address ,e.name,e.age FROM t_dept d LEFT JOIN t_emp e ON d.id = e.deptId WHERE e.id IS NULL)
七:MySQL子查询
子查询可以按照两种方式进行分类。若按照期望的数量,可以将子查询分为标量子查询(单行子查询)和多值子查询(多行子查询);若按查询对外部查询的依赖,可分为不相关子查询(self-contained subquery)和相关子查询(correlated subquery)。注:标量子查询和多值子查询既可以是独立子查询,也可以是相关子查询。
子查询是指在一个SELECT语句中嵌套另一个SELECT语句。MYSQL数据库从4.1版本开始支持子查询,并且支持所有SQL标准的子查询,
也扩展了一些其独有的子查询标准。下面是一个子查询:
SELECT * FROM t1 WHERE colimn1 = (SELECT column1 FROM t2);
在这个实例中,SELECT * FROM t1 是外部查询(outer query),SELECT column1 FROM t2 是子查询。
一般来说,称子查询嵌套(nested)于外部查询中。实际也可以将两个或两个以上的子查询进行嵌套。需要注意的是,子查询必须包含括号。
一个子查询会返回一个标量(单一值)、一个行、一个列或一个表(一行或多行及一列或多列),这些子查询被称为标量、行、列和表子查询。
可返回一个特定种类结果的子查询经常只能用于特定的语境中。子查询可以包括普通SELECT可以包含的任何关键词或子句,
如DISTINCT、GROUP BY、ORDER BY、LIMIT、JOIN、UNION等。但注意的是子查询语句只能在非GROUP BY和非LIMIT的外部查询里写子查询
子查询的限制是其外部语句必须是以下语句之一:SELECT、INSERT、UPDATE、DELETE、SET或DO。还有一个限制是,
目前我们修改一个表的时候子查询不能查询同一张表,虽然这样的操作可用于普通的DELETE、INSERT、REPLACE和UPDATE语句中,
但是对子查询不可以修改时进行这样的查询操作。
mysql1093报错:(这是一个修改时使用子查询查询修改的表)
1093错误为:修改一个表的时候子查询不能是同一个表,解决办法:把子查询再套一层,变成原来表的孙子查询就可以了,例如:
insert into gg set id3= (select c.a+1 from (select max(id3) as a from gg) c) 这是对的
但是 insert into gg set id3= (select max(id3) as a from gg) 就会报1093错误
1:一个简单的子查询案例(单行子查询)
查询其它学生零花钱(smoney)比 "丘耿徽" 零花钱高的其它学生
SELECT sname,smoney FROM student WHERE smoney > ( SELECT smoney FROM student WHERE sname = "丘耿徽"); 外查询:(查询比smoney条件大的数据) SELECT sname,smoney FROM student WHERE smoney > ? 子查询:(查询指定学生的零花钱) SELECT smoney FROM student WHERE sname = "丘耿徽" -- 注:子查询需要使用括号框住 SELECT s1.sname "姓名",s1.smoney "零花钱", s1.smoney - s2.smoney "相差金额" FROM student s1 INNER JOIN student s2 ON s1.smoney > s2.smoney WHERE s2.sname = "丘耿徽"
2:单行不相关子查询
> < >= <= = <> 注意:LIKE关键字后面也可以
SELECT * FROM student WHERE smoney > ( SELECT smoney FROM student WHERE sid = 50 ) SELECT * FROM student WHERE tid = ( SELECT tid FROM student WHERE sid = 25 ) AND smoney > ( SELECT smoney FROM student WHERE sid = 35 ) SELECT * FROM student WHERE smoney = (SELECT MIN(smoney) FROM student) SELECT * FROM student WHERE smoney IS NOT NULL ORDER BY smoney ASC LIMIT 1 SELECT * FROM student WHERE sage IN( SELECT sage FROM student WHERE sid IN(1,7) ) AND saddress IN( SELECT saddress FROM student WHERE sid IN(1,7) ) SELECT * FROM student WHERE (sage,saddress) IN( SELECT sage,saddress FROM student WHERE sid IN(1,7) ) SELECT t.tid,t.tname,MIN(s.smoney) "minMoney" FROM student s RIGHT JOIN teacher t USING(tid) GROUP BY s.tid HAVING minMoney > (SELECT MIN(smoney) FROM student WHERE tid = 3) SELECT sname, scredit, CASE WHEN scredit >= (SELECT scredit FROM student WHERE sid = 4) THEN "优秀" ELSE "一般" END AS level FROM student ORDER BY level
3:多行MySQL之DQL——查询语言
前言
今天给大家带来关于数据库查询相关操作,希望各位看官能看个愉快
目录
一、基本概念
在学习MySQL之前我们先来了一下几个基本概念:
1.1、基本概念
数据库 【DB(datebase)】:数据库指的是长期存在计算机内、有组织、可共享的、大量数据的集合。数据是按照特定的数据模型来组织、存储在数据库中的。
数据库管理系统【DBMS(Datebase Management System)】:又称为数据库软件(产品),用于管理DB中的数据
常见DBMS :MySQL,Oracle,DB2,SQLServer等
SQL :结构化查询语言,用于和数据库通信的语言
而我们学习的SQL语言又有哪些分类呢?
1.2、SQL语言的分类
DML(Data Manipulate Language):
数据操纵语言,用于添加、删除、修改数据库记录,并检查数据完整性
关键字:insert, delete, update 等
DDL(Data Define Languge):
数据定义语言,用于库和表的创建、修改、删除
关键字:create, drop,alter等
TCL(Data Control Language):
数据事务语言
DQL(Data Query Languag):
数据查询语言,用来查询数据库中表的记录(数据)
关键字:select, where 等
1.3、数据库的存储特点
1.将数据放到表中,表再放到数据库中
2.一个数据库中可以有多个表,每个表都有一个名字,用来标识自己,表名具有唯一性
3.表具有一些特性,这些特性定义了数据在表中如何存储,类似java中“类”的设计
4.表由列组成,我们也称为字段,所有表都是由一个或多个列组成的,每一列类似于就java中的“属性”
5.表中的数据都是按行存储的,每一行类似于java中的“对象”
二、MySQL
既然要学习数据库,我们就要下载数据库管理系统才可以,这里我们选用的MySQL,大家可以前往他的官网进行下载使用免费版本:MySQL。
安装好MySQL之后,我们需要启动他的服务:
2.1、 MySQL服务的登录和退出
方式一:通过MySQL自带的客户端
只限于root用户
方式二:通过cmd命令提示行关闭,未配置MySQL环境变量,需在MySQL安装的bin下启动cmd
登录:mysql 【-h主机名 -P端口号 】-u用户名 -p密码 (完整版,即远程登陆,可省略中口号中的代码,省略版仅支持登陆本机用户)
退出:
exit或ctrl+C
2.2、 MySQL服务的启动和停止
方式一:计算机——右击管理——服务——MySQL
方式二:通过管理员身份运行cmd命令提示行
net start mysql(启动服务)
net stop mysql(停止服务)
2.3、MySQL常见数据指令
常见MySQL数据指令
功能 代码 备注 1.查看所有的数据库 show databases ; 注意,分号之前要加空格,否则会报错 2.进入某个数据库指令 use 数据库名; 3.在数据库中查找表的指令 show tables; 4.在一个数据库中想要查看另一个数据库的表的指令 show tables from 数据库名 注意
使用该指令我们的用户依旧在原库,也就是test中,只是查看了mysql数据库中的表而已。 5.查找我目前所在库的位置 select database(); 6.创建新表指令
create table 表名(
字段名 类型;
……….); 7.查看表名结构 desc 表名; 8.查看表中数据 select * from 表名; 9.向表中添加数据 insert into 表名 (字段...) values(); 10.修改表中数据 update 表名 set 某字段= '修改后的值' where id=n; 这里的n是你自己表中字段所对应的ID 11.删除表中数据 delete from 表名 where id=n n就是你要删除的行对应的字段 12.查看MySQL版本方法 1.在进入MySQL数据中
1.select version();
2.退出MySQL数据库之后
(1).mysql --version
(2).mysql -V
2.4、MySQL语法规范
1.不区分大小写,但建议关键字大写,表名,列名小写
2.每条命令最好以分号结尾
3.每条命令根据需要,可以进行缩进,或换行
4.注释
单行注释
#注释文字
-- 注释文字
注意,--之后必须打空格
多行注释
/*注释文字*/
三、MySQL之DQL语言
在该部分我们学习以下内容:
基础查询、条件查询、排序查询、常见函数、分组函数、分组查询、连接查询、子查询、分页查询、union联合查询,内容较多,我们慢慢展开。
3.1、简单查询
在进行查询前呢我们最好下载一个图形化客户端进行操作,这里我学习用的SQLyog,大家可以在CSDN搜索如何下载和使用该软件,这里就不做过多介绍。
当我们第一次进行查询的时候,一定注意要进入你查询的数据库中才能进行查询操作。
3.1.1、简单查询语句语法
select 查询列表 from 表名;
他的意思,类似于java中的System.out.println(打印的内容),把我们查询的内容显示出来。
特点:
1、查询的列表可以是表中 的字段 ,常量值,表达式,函数
2、查询的结果是一个虚拟的表格
图示:
以下给大家介绍几种常用的操作
3.1.2、给字段起别名
语法:select 字段 AS 别名;
注意:如果别名与关键字冲突,别名应该使用双引号或者单引号括起来,建议使用双引号
起别名的好处:
1、便于理解
2、如果要查询的字段有重名的情况,使用别名可以区分开来
3.1.3、去重
语法:select distinct 字段 from 表名;
去重前:
去重之后:
很明显的看到我们去重之前有107行数据,而去重之后 仅剩余12行数据。
3.1.4、MySQL中+号的作用以及concat函数
在学习java的时候我们可以使用+号去做字符串拼接操作,但是,在MySQL中我们可以使用+号来完成字符串拼接的功能吗?很显然是不可以的。
MySQL中的+号的功能
仅仅只有一个功能 : 运算符
分为以下三种情况:
1、两个操作数都为数值型,则做加法运算
例如:select 100+90;
2、其中一方为字符型,试图将字符型数值转换为数值型
如果转换成功,则做加法运算
select '123'+90;
如果转换失败,则将字符型数值转换为0;
select 'hello' + 90;
3、只要其中一方为null,结果就一定是null;
select null + 90;
concat函数
那么在MySQL中,他也有自己的字符串拼接函数,就是concat
语法:concat(str1,str2....)
实例用法
3.1.5、ifnull函数
ifnull函数的含义:ifnull的执行是检查如果字段中有值为null的情况,没有则返回你设置的值
语法: select ifnull(原值字段,你设置的返回值)
图示:
3.2、条件查询
语法:
select
查询列表(第三步执行)
· from
表名(第一步执行)
where
筛选条件(第二部执行)
筛选条件我们可以大致分为三类:
3.2.1、按条件表达式筛选:
条件运算符:> < = != <> >= <=
3.2.2、按逻辑表达式筛选:
逻辑运算符:
逻辑运算符
&& || ! and or not
该连接符主要用于连接表达式
作用:
1、&&和and:两个条件都为true,则结果为true,反之为false
2、 ||和or:只要有一个条件为true,则结果为true,反之为false
3、!和not:如果连接的条件本身为false,则结果为true,否则为false
3.2.3、模糊查询:
该类连接符分类:
like,between and,in,is null,<=>(安全等于)
like:
该连接符的应用场景大多用于查询某个字段中包含某个字符等,一般和通配符搭配使用
通配符
% 任意多个字符,包含0个字符
_ 任意单个字符
between and:
他所查询的就是某个区间的值大多应用场景:也可以用条件表达式去完成
特点:
1、可以提高语句简洁度
2、两个区间的值的顺序不可颠倒
3、包含临界值
in:
判断某字段的值是否属于in列表中的某一项
注意特点:
①使用in提高了语句简洁度
②in列表的值必须是同一类型或兼容
③in字段不支持通配符
is null :
用于判断字段值是否为null
注意:
=或<>不能用于判断null值
is null 或 is not null可以判断null值
那么相反如果想要查询相反值就是is not null
安全等于 <=>:
与 isnull进行比较
isnull仅仅可以判断null值,可读性较高,建议使用
安全等于既可以判断null值,又可以判断普通的数值,可读性较低
3.3、排序查询
语法:
select
要查询的东西
from
表
where
条件
order by 排序的字段|表达式|函数|别名 【asc|desc】
排序方式:
* ASC:升序,默认的
* DESC:降序
特点
1.asc代表的是升序,desc代表的是降序
如果关键字不写,默认是升序
2.order by子句一般是放在查询语句的最后面,limit子句除外
3.order by子句中可以支持单个字段,多个字段,表达式,函数,别名
4.length函数表示返回字符串长度
3.4、常见函数
3.4.1、字符函数
concat: 拼接
substr: 截取子串
upper: 转换成大写
lower: 转换成小写
trim: 去前后指定的空格和字符
ltrim: 去左边空格
rtrim: 去右边空格
replace: 替换
lpad: 左填充
rpad: 右填充
instr: 返回子串第一次出现的索引
length: 获取字节个数
3.4.2、数学函数
rand: 随机数
floor: 向下取整
返回<=该参数的最大整数
ceil: 向上取整
返回>=该参数的最小整数
mod: 取余
truncate: 截断
rand:获取随机数,取值范围0-1
3.4.3、日期函数
now: 当前系统日期+时间
curdate: 当前系统日期
curtime: 当前系统时间
str_to_date: 将字符转换成日期
date_format: 将日期转换成字符
datediff:两个日期相差天数
monthname:以英文形式返回月
3.4.4、其他函数
database: 当前库
user: 当前连接用户
version: 版本
password(‘字符’):返回该字符的加密形式
md5('字符'):返回该字符的md5加密形式
3.4.5、流程控制函数
该函数式MySQL中比较重要的函数
首先是case函数
他分为两种使用方法:
(一):
类似于java中的Switch case函数
语法:
case 要判断的字段或表达式
when 常量1 then 要显示的值1或语句1;
when 常量2 then 要显示的值2或语句2;
...
else 要显示的值n或语句n;
end
案例:
(二):
类似于java中的多重if语句
语法:
case
when 条件1 then 要显示的值1或语句1(语句要加分号)
when 条件2 then 要显示的值2或语句2
。。。
else 要显示的值n或语句n
end
案例:
其次是if函数:
类似于if else效果:
案例:
3.5、分组函数
* count:计算个数
* 一般选择非空的列:主键
* count(*)
表示统计表中所有行数,包括null
* max:计算最大值
* min:计算最小值
* sum:计算和
* avg:计算平均值
注意:
1、以上五个分组函数都忽略null值,除了 count(*)
2、sum和avg一般用于处理数值型,max、min、count可以处理任何数据类型
3、都可以搭配distinct使用,用于统计去重后的结果
4、count的参数可以支持:
字段、*、常量值,一般放1
效率
MYISAM存储引擎下 ,COUNT(*)的效率高
INNODB存储引擎下,COUNT(*)和COUNT(1)的效率差不多,比COUNT(字段)要高一些
5.和分组函数一同查询的字段要求是group by后的字段(group by是3.6分组查询的语句)
3.6、分组查询
语法:
select 查询的字段,分组函数
from 表
group by 分组的字段
特点:
1、可以按单个字段分组
2、和分组函数一同查询的字段最好是分组后的字段
3、可以按多个字段分组,字段之间用逗号隔开
4、可以支持排序
5、having后可以支持别名
注意:
分组函数做筛选不能放在where后面
能做分组前筛选的,尽量选择分组前筛选,以提高效率
分组可以按单个字段也可以按多个字段并且可以搭配着排序使用
题外话:
where 和 having 的区别?
1. where 在分组之前进行限定,如果不满足条件,则不参与分组。having在分组之后进行限定,如果不满足结果,则不会被查询出来
2. where 后不可以跟聚合函数,having可以进行聚合函数的判断。
3.7、连接查询
含义:又称多表查询,当查询的字段来自于多个表时,就会用到连接查询
在我们对表进行查询操作时,会出先一个现象就是我们有一个表由m行,另一个表由n行,而当我们对两张表进行连接查询时,对连接条件进行了错误的添加,就会出现m*n行数据,那么这肯定不是我们想要的结果,因为他包含了太多重复的无用的数据,该现象就叫做笛卡尔乘积效应:
发生原因:
1. 省略连接条件
2. 连接条件无效
3. 所有表中所有行互相连接
如何解决:
添加有效的连接条件
3.7.1、连接查询的分类:
3.7.2、sql92标准下的连接查询
它只支持内连接中的等值连接,非等值连接,自连接
语法:
SELECT 查询列表
FROM 表名1 别名1 ,表名2 别名2
WHERE 连接条件 【等值连接,非等值连接,自连接】
AND 筛选条件
GROUP BY 分组列表
HAVING 分组后筛选条件
ORDER BY 排序列表
等值连接,什么意思呢?
①多表等值连接的结果为多表的交集部分
②n表连接,至少需要n-1个连接条件
③多表的顺序一般没有要求
④一般需要为表起别名
⑤可以搭配前面介绍的所有子句使用,比如排序,分组,筛选
连接条件为等于号
举例:
非等值连接:连接条件不为等于号
举例:
很明显这里的连接条件是between and
自连接:自己表中内容进行连接,
自连接需要注意对表起别名作区分
3.7.3、sql99标准下的连接查询
内连接:
语法:
select 字段列表
from 表名1
[inner] join 表名2 on 条件
where 筛选条件【等值连接,非等值连接,自连接】
group by 分组条件
having 分组后的筛选条件
order by 排序字段
等值连接:
①添加排序、分组、筛选
②inner可以省略
③ 筛选条件放在where后面,连接条件放在on后面,提高分离性,便于阅读
④inner join连接和sql92语法中的等值连接效果是一样的,都是查询多表的交集
实例:
非等值连接:连接条件不为等号
实例:
自连接:在自己表内为连接条件
实例:
外连接:
应用场景:用于查询一个表中有,另一个表没有的记录
特点:
1、外连接的查询结果为主表中的所有记录
如果从表中有和它匹配的,则显示匹配的值
如果从表中没有和它匹配的,则显示null
外连接查询结果=内连接结果+主表中有而从表没有的记录
2、左外连接,left join左边的是主表
右外连接,right join右边的是主表
3、左外和右外交换两个表的顺序,可以实现同样的效果
4、全外连接=内连接的结果+表1中有但表2没有的+表2中有但表1没有的
左外连接:
select 字段列表
from 表名1
left[outer] join 表名2 on 条件
where 筛选条件
group by 分组条件
having 分组后的筛选条件
order by 排序字段
右外连接:
语法:
select 字段列表
from 表名1
right[outer] join 表名2 on 条件
where 筛选条件
group by 分组条件
having 分组后的筛选条件
order by 排序字段
实例:
全外由于MySQL不支持,因此这里只了解其语法:
select 字段列表
from 表名1
full[outer] join 表名2 on 条件
where 筛选条件
group by 分组条件
having 分组后的筛选条件
order by 排序字段
交叉连接:
语法:
select 字段列表
from 表名1
cross join 表名2 on 条件
where 筛选条件
group by 分组条件
having 分组后的筛选条件
order by 排序字段
就是笛卡尔乘积
实例:
3.8、子查询
含义:
出现在其他语句(不仅限于查询语句)中的select语句,称为子查询或内查询
外部的查询语句,称为主查询或外查询
分类:
select语句后面仅仅支持标量子查询
from后面:支持表子查询:将子查询结果充当一张表,要求必须起别名
实例:
exists后面(相关子查询)
查询的括号内一般是一个连接查询
语法:
exists(完整的查询语句)
结果:1或0
实例:
where或having后面支持:
标量子查询
列子查询
行子查询
where或having后面标量子查询:
特点:
①子查询放在小括号内
②子查询一般放在条件的右侧
③标量子查询,一般搭配着单行操作符使用
> < >= <= = <>
列子查询,一般搭配着多行操作符使用
in、any/some、all
④子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果
where或having后面行子查询
实例:
where或having后面列子查询
列子查询一般搭配逻辑操作符使用:
实例:
3.9、分页查询
应用场景:当要显示的数据,一页显示不全,需要分页提交sql请求
语法:
select 查询列表
from 表
【join type join 表2
on 连接条件
where 筛选条件
group by 分组字段
having 分组后的筛选
order by 排序的字段】
limit 【offset,】size;
offset要显示条目的起始索引(起始索引从0开始)
size 要显示的条目个数
特点:
①limit语句放在查询语句的最后
②公式
要显示的页数 page,每页的条目数size
select 查询列表
from 表
limit (page-1)*size,size;
3.10、联合查询
应用场景:
要查询的结果来自于多个表,且多个表之间没有任何直接的连接关系
但查询的信息一致时(即两张表查询的信息相同)
含义:将多条查询语句的结果合并成一个结果
特点:
1、要求多条查询语句的查询列数是一致的
2、要求多条查询语句查询的每一列的类型和顺序最好一致
3、union关键字默认去重,如果使用union all可以包含重复项
语法:
查询语句1
union
查询语句2
union
......
写在最后:
最后,求三连关注啊 ,后面会给大家带来其他操作哦。下次见
以上是关于MySQL之DQL数据查询操作的主要内容,如果未能解决你的问题,请参考以下文章
前言
今天给大家带来关于数据库查询相关操作,希望各位看官能看个愉快
目录
一、基本概念
在学习MySQL之前我们先来了一下几个基本概念:
1.1、基本概念
数据库 【DB(datebase)】:数据库指的是长期存在计算机内、有组织、可共享的、大量数据的集合。数据是按照特定的数据模型来组织、存储在数据库中的。
数据库管理系统【DBMS(Datebase Management System)】:又称为数据库软件(产品),用于管理DB中的数据
常见DBMS :MySQL,Oracle,DB2,SQLServer等
SQL :结构化查询语言,用于和数据库通信的语言
而我们学习的SQL语言又有哪些分类呢?
1.2、SQL语言的分类
DML(Data Manipulate Language):
数据操纵语言,用于添加、删除、修改数据库记录,并检查数据完整性
关键字:insert, delete, update 等
DDL(Data Define Languge):
数据定义语言,用于库和表的创建、修改、删除
关键字:create, drop,alter等
TCL(Data Control Language):
数据事务语言
DQL(Data Query Languag):
数据查询语言,用来查询数据库中表的记录(数据)
关键字:select, where 等
1.3、数据库的存储特点
1.将数据放到表中,表再放到数据库中
2.一个数据库中可以有多个表,每个表都有一个名字,用来标识自己,表名具有唯一性
3.表具有一些特性,这些特性定义了数据在表中如何存储,类似java中“类”的设计
4.表由列组成,我们也称为字段,所有表都是由一个或多个列组成的,每一列类似于就java中的“属性”
5.表中的数据都是按行存储的,每一行类似于java中的“对象”
二、MySQL
既然要学习数据库,我们就要下载数据库管理系统才可以,这里我们选用的MySQL,大家可以前往他的官网进行下载使用免费版本:MySQL。
安装好MySQL之后,我们需要启动他的服务:
2.1、 MySQL服务的登录和退出
方式一:通过MySQL自带的客户端
只限于root用户
方式二:通过cmd命令提示行关闭,未配置MySQL环境变量,需在MySQL安装的bin下启动cmd
登录:mysql 【-h主机名 -P端口号 】-u用户名 -p密码 (完整版,即远程登陆,可省略中口号中的代码,省略版仅支持登陆本机用户)
退出:
exit或ctrl+C
2.2、 MySQL服务的启动和停止
方式一:计算机——右击管理——服务——MySQL
方式二:通过管理员身份运行cmd命令提示行
net start mysql(启动服务)
net stop mysql(停止服务)
2.3、MySQL常见数据指令
功能 | 代码 | 备注 |
---|---|---|
1.查看所有的数据库 | show databases ; | 注意,分号之前要加空格,否则会报错 |
2.进入某个数据库指令 | use 数据库名; | |
3.在数据库中查找表的指令 | show tables; | |
4.在一个数据库中想要查看另一个数据库的表的指令 | show tables from 数据库名 | 注意 使用该指令我们的用户依旧在原库,也就是test中,只是查看了mysql数据库中的表而已。 |
5.查找我目前所在库的位置 | select database(); | |
6.创建新表指令 | create table 表名( 字段名 类型; ……….); | |
7.查看表名结构 | desc 表名; | |
8.查看表中数据 | select * from 表名; | |
9.向表中添加数据 | insert into 表名 (字段...) values(); | |
10.修改表中数据 | update 表名 set 某字段= '修改后的值' where id=n; | 这里的n是你自己表中字段所对应的ID |
11.删除表中数据 | delete from 表名 where id=n | n就是你要删除的行对应的字段 |
12.查看MySQL版本方法 | 1.在进入MySQL数据中 2.退出MySQL数据库之后 |
2.4、MySQL语法规范
1.不区分大小写,但建议关键字大写,表名,列名小写
2.每条命令最好以分号结尾
3.每条命令根据需要,可以进行缩进,或换行
4.注释
单行注释
#注释文字
-- 注释文字
注意,--之后必须打空格
多行注释
/*注释文字*/
三、MySQL之DQL语言
在该部分我们学习以下内容:
基础查询、条件查询、排序查询、常见函数、分组函数、分组查询、连接查询、子查询、分页查询、union联合查询,内容较多,我们慢慢展开。
3.1、简单查询
在进行查询前呢我们最好下载一个图形化客户端进行操作,这里我学习用的SQLyog,大家可以在CSDN搜索如何下载和使用该软件,这里就不做过多介绍。
当我们第一次进行查询的时候,一定注意要进入你查询的数据库中才能进行查询操作。
3.1.1、简单查询语句语法
select 查询列表 from 表名;
他的意思,类似于java中的System.out.println(打印的内容),把我们查询的内容显示出来。
特点:
1、查询的列表可以是表中 的字段 ,常量值,表达式,函数
2、查询的结果是一个虚拟的表格
图示:
以下给大家介绍几种常用的操作
3.1.2、给字段起别名
语法:select 字段 AS 别名;
注意:如果别名与关键字冲突,别名应该使用双引号或者单引号括起来,建议使用双引号
起别名的好处:
1、便于理解
2、如果要查询的字段有重名的情况,使用别名可以区分开来
3.1.3、去重
语法:select distinct 字段 from 表名;
去重前:
去重之后:
很明显的看到我们去重之前有107行数据,而去重之后 仅剩余12行数据。
3.1.4、MySQL中+号的作用以及concat函数
在学习java的时候我们可以使用+号去做字符串拼接操作,但是,在MySQL中我们可以使用+号来完成字符串拼接的功能吗?很显然是不可以的。
MySQL中的+号的功能
仅仅只有一个功能 : 运算符
分为以下三种情况:
1、两个操作数都为数值型,则做加法运算
例如:select 100+90;
2、其中一方为字符型,试图将字符型数值转换为数值型
如果转换成功,则做加法运算
select '123'+90;
如果转换失败,则将字符型数值转换为0;
select 'hello' + 90;
3、只要其中一方为null,结果就一定是null;
select null + 90;
concat函数
那么在MySQL中,他也有自己的字符串拼接函数,就是concat
语法:concat(str1,str2....)
实例用法
3.1.5、ifnull函数
ifnull函数的含义:ifnull的执行是检查如果字段中有值为null的情况,没有则返回你设置的值
语法: select ifnull(原值字段,你设置的返回值)
图示:
3.2、条件查询
语法:
select
查询列表(第三步执行)
· from
表名(第一步执行)
where
筛选条件(第二部执行)
筛选条件我们可以大致分为三类:
3.2.1、按条件表达式筛选:
条件运算符:> < = != <> >= <=
3.2.2、按逻辑表达式筛选:
逻辑运算符:
&& | || | ! |
and | or | not |
该连接符主要用于连接表达式
作用:
1、&&和and:两个条件都为true,则结果为true,反之为false
2、 ||和or:只要有一个条件为true,则结果为true,反之为false
3、!和not:如果连接的条件本身为false,则结果为true,否则为false
3.2.3、模糊查询:
该类连接符分类:
like,between and,in,is null,<=>(安全等于)
like:
该连接符的应用场景大多用于查询某个字段中包含某个字符等,一般和通配符搭配使用
通配符
% 任意多个字符,包含0个字符
_ 任意单个字符
between and:
他所查询的就是某个区间的值大多应用场景:也可以用条件表达式去完成
特点:
1、可以提高语句简洁度
2、两个区间的值的顺序不可颠倒
3、包含临界值
in:
判断某字段的值是否属于in列表中的某一项
注意特点:
①使用in提高了语句简洁度
②in列表的值必须是同一类型或兼容
③in字段不支持通配符
is null :
用于判断字段值是否为null
注意:
=或<>不能用于判断null值
is null 或 is not null可以判断null值
那么相反如果想要查询相反值就是is not null
安全等于 <=>:
与 isnull进行比较
isnull仅仅可以判断null值,可读性较高,建议使用
安全等于既可以判断null值,又可以判断普通的数值,可读性较低
3.3、排序查询
语法:
select
要查询的东西
from
表
where
条件
order by 排序的字段|表达式|函数|别名 【asc|desc】
排序方式:
* ASC:升序,默认的
* DESC:降序
特点
1.asc代表的是升序,desc代表的是降序
如果关键字不写,默认是升序
2.order by子句一般是放在查询语句的最后面,limit子句除外
3.order by子句中可以支持单个字段,多个字段,表达式,函数,别名
4.length函数表示返回字符串长度
3.4、常见函数
3.4.1、字符函数
concat: 拼接
substr: 截取子串
upper: 转换成大写
lower: 转换成小写
trim: 去前后指定的空格和字符
ltrim: 去左边空格
rtrim: 去右边空格
replace: 替换
lpad: 左填充
rpad: 右填充
instr: 返回子串第一次出现的索引
length: 获取字节个数
3.4.2、数学函数
rand: 随机数
floor: 向下取整
返回<=该参数的最大整数
ceil: 向上取整
返回>=该参数的最小整数
mod: 取余
truncate: 截断
rand:获取随机数,取值范围0-1
3.4.3、日期函数
now: 当前系统日期+时间
curdate: 当前系统日期
curtime: 当前系统时间
str_to_date: 将字符转换成日期
date_format: 将日期转换成字符
datediff:两个日期相差天数
monthname:以英文形式返回月
3.4.4、其他函数
database: 当前库
user: 当前连接用户
version: 版本
password(‘字符’):返回该字符的加密形式
md5('字符'):返回该字符的md5加密形式
3.4.5、流程控制函数
该函数式MySQL中比较重要的函数
首先是case函数
他分为两种使用方法:
(一):
类似于java中的Switch case函数
语法:
case 要判断的字段或表达式
when 常量1 then 要显示的值1或语句1;
when 常量2 then 要显示的值2或语句2;
...
else 要显示的值n或语句n;
end
案例:
(二):
类似于java中的多重if语句
语法:
case
when 条件1 then 要显示的值1或语句1(语句要加分号)
when 条件2 then 要显示的值2或语句2
。。。
else 要显示的值n或语句n
end
案例:
其次是if函数:
类似于if else效果:
案例:
3.5、分组函数
* count:计算个数
* 一般选择非空的列:主键
* count(*)
表示统计表中所有行数,包括null
* max:计算最大值
* min:计算最小值
* sum:计算和
* avg:计算平均值
注意:
1、以上五个分组函数都忽略null值,除了 count(*)
2、sum和avg一般用于处理数值型,max、min、count可以处理任何数据类型
3、都可以搭配distinct使用,用于统计去重后的结果
4、count的参数可以支持:
字段、*、常量值,一般放1
效率
MYISAM存储引擎下 ,COUNT(*)的效率高
INNODB存储引擎下,COUNT(*)和COUNT(1)的效率差不多,比COUNT(字段)要高一些
5.和分组函数一同查询的字段要求是group by后的字段(group by是3.6分组查询的语句)
3.6、分组查询
语法:
select 查询的字段,分组函数
from 表
group by 分组的字段
特点:
1、可以按单个字段分组
2、和分组函数一同查询的字段最好是分组后的字段
3、可以按多个字段分组,字段之间用逗号隔开
4、可以支持排序
5、having后可以支持别名
注意:
分组函数做筛选不能放在where后面
能做分组前筛选的,尽量选择分组前筛选,以提高效率
分组可以按单个字段也可以按多个字段并且可以搭配着排序使用
题外话:
where 和 having 的区别?
1. where 在分组之前进行限定,如果不满足条件,则不参与分组。having在分组之后进行限定,如果不满足结果,则不会被查询出来
2. where 后不可以跟聚合函数,having可以进行聚合函数的判断。
3.7、连接查询
含义:又称多表查询,当查询的字段来自于多个表时,就会用到连接查询
在我们对表进行查询操作时,会出先一个现象就是我们有一个表由m行,另一个表由n行,而当我们对两张表进行连接查询时,对连接条件进行了错误的添加,就会出现m*n行数据,那么这肯定不是我们想要的结果,因为他包含了太多重复的无用的数据,该现象就叫做笛卡尔乘积效应:
发生原因:
1. 省略连接条件
2. 连接条件无效
3. 所有表中所有行互相连接如何解决:
添加有效的连接条件
3.7.1、连接查询的分类:
3.7.2、sql92标准下的连接查询
它只支持内连接中的等值连接,非等值连接,自连接
语法:
SELECT 查询列表
FROM 表名1 别名1 ,表名2 别名2
WHERE 连接条件 【等值连接,非等值连接,自连接】
AND 筛选条件
GROUP BY 分组列表
HAVING 分组后筛选条件
ORDER BY 排序列表
等值连接,什么意思呢?
①多表等值连接的结果为多表的交集部分
②n表连接,至少需要n-1个连接条件
③多表的顺序一般没有要求
④一般需要为表起别名
⑤可以搭配前面介绍的所有子句使用,比如排序,分组,筛选
连接条件为等于号
举例:
非等值连接:连接条件不为等于号
举例:
很明显这里的连接条件是between and
自连接:自己表中内容进行连接,
自连接需要注意对表起别名作区分
3.7.3、sql99标准下的连接查询
内连接:
语法:
select 字段列表
from 表名1
[inner] join 表名2 on 条件
where 筛选条件【等值连接,非等值连接,自连接】
group by 分组条件
having 分组后的筛选条件
order by 排序字段
等值连接:
①添加排序、分组、筛选
②inner可以省略
③ 筛选条件放在where后面,连接条件放在on后面,提高分离性,便于阅读
④inner join连接和sql92语法中的等值连接效果是一样的,都是查询多表的交集
实例:
非等值连接:连接条件不为等号
实例:
自连接:在自己表内为连接条件
实例:
外连接:
应用场景:用于查询一个表中有,另一个表没有的记录
特点:
1、外连接的查询结果为主表中的所有记录
如果从表中有和它匹配的,则显示匹配的值
如果从表中没有和它匹配的,则显示null
外连接查询结果=内连接结果+主表中有而从表没有的记录
2、左外连接,left join左边的是主表
右外连接,right join右边的是主表
3、左外和右外交换两个表的顺序,可以实现同样的效果
4、全外连接=内连接的结果+表1中有但表2没有的+表2中有但表1没有的左外连接:
select 字段列表
from 表名1
left[outer] join 表名2 on 条件
where 筛选条件
group by 分组条件
having 分组后的筛选条件
order by 排序字段
右外连接:
语法:
select 字段列表
from 表名1
right[outer] join 表名2 on 条件
where 筛选条件
group by 分组条件
having 分组后的筛选条件
order by 排序字段
实例:
全外由于MySQL不支持,因此这里只了解其语法:
select 字段列表
from 表名1
full[outer] join 表名2 on 条件
where 筛选条件
group by 分组条件
having 分组后的筛选条件
order by 排序字段
交叉连接:
语法:
select 字段列表
from 表名1
cross join 表名2 on 条件
where 筛选条件
group by 分组条件
having 分组后的筛选条件
order by 排序字段就是笛卡尔乘积
实例:
3.8、子查询
含义:
出现在其他语句(不仅限于查询语句)中的select语句,称为子查询或内查询
外部的查询语句,称为主查询或外查询
分类:
select语句后面仅仅支持标量子查询
from后面:支持表子查询:将子查询结果充当一张表,要求必须起别名
实例:
exists后面(相关子查询)
查询的括号内一般是一个连接查询语法:
exists(完整的查询语句)
结果:1或0
实例:
where或having后面支持:
标量子查询
列子查询
行子查询
where或having后面标量子查询:
特点:
①子查询放在小括号内
②子查询一般放在条件的右侧
③标量子查询,一般搭配着单行操作符使用
> < >= <= = <>
列子查询,一般搭配着多行操作符使用
in、any/some、all
④子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果
where或having后面行子查询
实例:
where或having后面列子查询
列子查询一般搭配逻辑操作符使用:
实例:
3.9、分页查询
应用场景:当要显示的数据,一页显示不全,需要分页提交sql请求
语法:
select 查询列表
from 表
【join type join 表2
on 连接条件
where 筛选条件
group by 分组字段
having 分组后的筛选
order by 排序的字段】
limit 【offset,】size;offset要显示条目的起始索引(起始索引从0开始)
size 要显示的条目个数特点:
①limit语句放在查询语句的最后
②公式
要显示的页数 page,每页的条目数size
select 查询列表
from 表
limit (page-1)*size,size;
3.10、联合查询
应用场景:
要查询的结果来自于多个表,且多个表之间没有任何直接的连接关系
但查询的信息一致时(即两张表查询的信息相同)含义:将多条查询语句的结果合并成一个结果
特点:
1、要求多条查询语句的查询列数是一致的
2、要求多条查询语句查询的每一列的类型和顺序最好一致
3、union关键字默认去重,如果使用union all可以包含重复项语法:
查询语句1
union
查询语句2
union
......
写在最后:
最后,求三连关注啊 ,后面会给大家带来其他操作哦。下次见