MySQL數(shù)據(jù)庫原理與實踐指南之基本查詢
本篇目標
- 掌握 create,
select語句的基本使用方法。 - 掌握查詢指定列、查詢所有列以及為查詢結果設置別名的方法。
- 掌握使用
distinct對查詢結果進行去重。 - 掌握在查詢中使用算術表達式,對字段數(shù)據(jù)進行計算。
- 掌握使用
where子句對數(shù)據(jù)進行條件篩選。 - 掌握比較運算符、邏輯運算符、范圍查詢和模糊查詢的使用。
- 掌握使用
order by對查詢結果進行升序或降序排列。 - 掌握使用
limit限制查詢結果的數(shù)量,實現(xiàn)數(shù)據(jù)分頁。 - 能夠根據(jù)實際需求組合使用各種查詢條件,完成基本的數(shù)據(jù)檢索操作。
一.表的增刪改查
1.創(chuàng)建操作
1.1.create-創(chuàng)建表
基本語法:
create table [if not exists] 表名
(
字段名 數(shù)據(jù)類型 字段約束,
字段名 數(shù)據(jù)類型 字段約束
);例如:
CREATE TABLE students (
id int unsigned primary key auto_increment,
sn int not null unique comment '學號',
name varchar(20) not null,
qq varchar(20)
);1.2.insert-插入
<1>.單行數(shù)據(jù) + 全列插入
插入兩條記錄,value_list 數(shù)量必須和定義表的列的數(shù)量及順序一致
注意:這里在插入的時候,也可以不用指定id(當然,指定的時候就需要明確插入數(shù)據(jù)到那些列),那么mysql會使用默認的值進行自增。
操作:
insert into students values (100, 10000, '唐三藏', null); insert into students values (101, 10001, '哥倫比婭', '11111'); mysql> insert into students values (102, 10002, '桑多涅', '11111');
使用select來查看插入結果,如圖:

<2>.多行數(shù)據(jù) + 指定列插入
插入兩條記錄,value_list 數(shù)量必須和指定列數(shù)量及順序一致。
insert into students (id, sn, name) values (103, 20001, '曹孟德'),(104, 20002, '孫仲謀');
使用select來查看插入結果,如圖:

<3>.插入后檢查是否更新
由于 主鍵/唯一鍵對應的值已經(jīng)存在而導致插入失敗,此時我們可以選擇性的進行同步更新操作語法。
例如:
insert into students (id, sn, name) values (100, 10010, '唐大師'); insert into students (sn, name) values (20001, '曹阿瞞');
如圖:

一個是主鍵沖突,另一個是唯一鍵沖突。
此時需要用到更新這個操作,語法:
insert into 表名 [(字段列表)] values (值列表) on duplicate key update 字段名1 = 新值1,字段名2 = 新值2,...;
例如:
insert into students (id,sn,name) values (100,10010,'唐大師') on duplicate key update sn=10010,name='唐大師';
如圖:

這時候就會有人好奇:這個2 rows affected是什么意思?
0 row affected:表中有沖突數(shù)據(jù),但沖突數(shù)據(jù)的值和 update 的值相等。
1 row affected:表中沒有沖突數(shù)據(jù),數(shù)據(jù)被插入。
2 row affected:表中有沖突數(shù)據(jù),并且數(shù)據(jù)已經(jīng)被更新。
通過 MySQL 函數(shù)獲取受到影響的數(shù)據(jù)行數(shù):
select count();
如圖:

1.3.replace-替換
語法:
replace [into] 表名 [(字段名列表)] values (值列表) [, (值列表)] ...;
示例:
replace into students (id, sn, name) values (100, 10010, '唐大師');
如圖:

執(zhí)行邏輯:
- 如果不存在主鍵或唯一鍵沖突,則直接插入數(shù)據(jù)。
- 如果存在主鍵或唯一鍵沖突,則先刪除原來的記錄,再插入新的記錄。
解釋一下這個:
1 row affected:沒有發(fā)生沖突,直接插入一條新記錄。
2 rows affected:與一條舊記錄發(fā)生沖突,先刪除一條,再插入一條。
3 rows affected:新數(shù)據(jù)同時與兩條不同的舊記錄發(fā)生唯一鍵沖突,刪除兩條,再插入一條。
計算方式:
受影響行數(shù) = 刪除的舊記錄數(shù)量 + 插入的新記錄數(shù)量
例如這個是之前的students,如圖:

可是如果我們故意插入一個id為102的數(shù)據(jù)呢?
replace into students (id, sn, name) values (102, 10010, '唐大師');
插入后的students,如圖:

可以看出之前id為102的數(shù)據(jù)是已經(jīng)被刪除了的,并且在原來的位置上插入新的數(shù)據(jù)。
2.查詢操作
先創(chuàng)建表結構,操作:
create table exam_result (
id int unsigned primary key auto_increment,
name varchar(20) not null comment '同學姓名',
chinese float default 0.0 comment '語文成績',
math float default 0.0 comment '數(shù)學成績',
english float default 0.0 comment '英語成績'
);插入測試數(shù)據(jù),操作:
insert into exam_result (name, chinese, math, english) values
('唐三藏', 67, 98, 56),
('孫悟空', 87, 78, 77),
('豬悟能', 88, 98, 90),
('曹孟德', 82, 84, 67),
('劉玄德', 55, 85, 45),
('孫權', 70, 73, 78),
('宋公明', 75, 65, 30);2.1.select-查詢
<1>.全列查詢
通常情況下不建議使用 * 進行全列查詢,原因:
1. 查詢的列越多,意味著需要傳輸?shù)臄?shù)據(jù)量越大;
2. 可能會影響到索引的使用。
操作:
select * from exam_result;
如圖:

<2>.指定列查詢
我們在查詢的時候,指定列的順序不需要按定義表的順序來
操作:
select id, name, english FROM exam_result;
如圖:

<3>.查詢字段為表達式
表達式不包含字段時:

表達式包含多個字段:

<4>.為查詢結果指定別名
語法:
SELECT column [AS] alias_name(別名) [...] FROM table_name;
操作:
select id, name, chinese + math + english 總分 from exam_result;
如圖:

<5>.結果去重
distinct用于去除查詢結果中完全重復的記錄。
基本語法:
select distinct 字段列表 from 表名;
操作:
select distinct math from exam_result;


2.2.where條件
2.2.1.運算符
<1>.比較運算符:
| 運算符 | 說明 |
| >, >=, <, <= | 大于,大于等于,小于,小于等于 |
| = | 等于,NULL 不安全,例如 NULL = NULL 的結果是 NULL |
| <=> | 等于,NULL 安全,例如 NULL NULL 的結果是 TRUE(1) |
| !=, <> | 不等于 |
| between a0 and a1 | 范圍匹配,[a0, a1],如果 a0 <= value <= a1,返回 TRUE(1) |
| IN (option, ...) | 如果是 option 中的任意一個,返回 TRUE(1) |
| is null | 是null |
| is not null | 不是 null |
| like | 模糊匹配。% 表示任意多個(包括 0 個)任意字符;_ 表示任意一個字符 |
<2>.邏輯運算符:
| 運算符 | 說明 |
| and | 多個條件必須都為 TRUE(1),結果才是 TRUE(1) |
| or | 任意一個條件為 TRUE(1), 結果為 TRUE(1) |
| not | 條件為 TRUE(1),結果為 FALSE(0) |
2.2.2.案例演示
<1>.英語不及格的同學及英語成績 ( < 60 ),操作:
SELECT name, english FROM exam_result WHERE english < 60;
如圖:

<2>.語文成績在 [80, 90] 分的同學及語文成績,此時要用and做連接,操作:
select name,chinese from exam_result where chinese>=80 and chinese<=90;
如圖:

當然也可以用between...and...了,操作:
select name,chinese from exam_result where chinese between 80 and 90;
<3>.數(shù)學成績是 58 或者 59 或者 98 或者 99 分的同學及數(shù)學成績
可以使用使用or進行條件連接,操作:
select name,math from exam_result where math=58 or math=59 or math=98 or math=99;
如圖:

也可以使用使用 in條件,操作:
select name, math from exam_result where math in (58, 59, 98, 99);
如圖:

<4>.姓孫的同學及孫某同學
% 匹配任意多個(包括 0 個)任意字符,操作:
select name from exam_result where name like '孫%';
如圖:

_ 匹配嚴格的一個任意字符,可以添加多個_,操作:
select name from exam_result where name like '孫_'; select name from exam_result where name like '孫__'; select name from exam_result where name like '孫___';
如圖:

<5>.語文成績好于英語成績的同學
where 條件中比較運算符兩側(cè)都是字段,操作:
select name, chinese, english from exam_result where chinese > english;
如圖:

<6>.總分在 200 分以下的同學
可以在WHERE 條件中使用表達式,操作:
select name, chinese + math + english 總分 from exam_result where 總分 <200;
報錯原因是:總分通過 select設置的別名,而 where的執(zhí)行早于 select。執(zhí)行 where時,總分這個別名還沒有產(chǎn)生,所以MySQL認為它是一個不存在的字段。
修改后的:
select name, chinese + math + english 總分 from exam_result where chinese+math+english <200;
<7>.語文成績 > 80 并且不姓孫的同學
and 與 not 的使用,操作:
select name, chinese from exam_result where chinese > 80 and name not like '孫%';
如圖:

<8>.孫某同學,否則要求總成績 > 200 并且 語文成績 < 數(shù)學成績并且英語成績 > 80
操作:
select name, chinese, math, english, chinese + math + english 總分 from exam_result where name like '孫_' or ( chinese + math + english > 200 and chinese < math and english > 80 );

2.2.3.NULL 的查詢
查詢 students 表,操作如圖:

查詢 qq 號已知的同學姓名,操作:
select name,qq from students where qq is not null;
如圖:

<1>.NULL 和 NULL 的比較,= 和<=> 的區(qū)別
在MySQL中,null表示“未知值”,不是普通的數(shù)據(jù)。因此,不能使用普通的 =判斷兩個 null是否相等。
1. 使用=
select null = null;
結果:

因為兩個未知值無法判斷是否相等,所以結果既不是 true(1),也不是 false(0),而是 null。
下面的結果也都是 null:
select null = 10; select null != 10; select null <> 10;
2.使用<=>
<=>是MySQL提供的 null安全等于運算符。
select null <=> null; select null <=> 10;
結果:

2.3.結果排序
MySQL使用 order by對查詢結果進行排序。
基本語法:
select 字段列表 from 表名 [where 篩選條件] order by 排序字段 [asc | desc];
注意:asc 為升序(從小到大),desc 為降序(從大到?。?,默認為 asc。
<1>.同學及數(shù)學成績,按數(shù)學成績升序顯示
操作:
select math from exam_result order by math; select math from exam_result order by math desc;
如圖:

<2>.同學及 qq 號,按 qq 號排序顯示
操作:
select name, qq from students order by qq;
如圖:

注意:NULL 視為比任何值都小,升序出現(xiàn)在最上面
<3>.查詢同學各門成績,依次按 數(shù)學降序,英語升序,語文升序的方式顯示
操作:
select name, math, english, chinese from exam_result order by math desc, english, chinese;

<4>.查詢同學及總分,由高到低
order by 中可以使用表達式:
操作:
select name, chinese + english + math from exam_result order by chinese + english + math desc;

order by 子句中可以使用列別名:
操作:
select name, chinese + english + math 總分 from exam_result order by 總分 desc;
如圖:

可以使用別名的原因:
執(zhí)行順序:
from exam_result
↓
select name, chinese + english + math 總分
↓
order by 總分 desc
↓
返回排序后的結果也就是因為執(zhí)行 order by時,select已經(jīng)產(chǎn)生了 總分別名,所以這里可以直接使用 總分。
<5>.查詢姓孫的同學或者姓曹的同學數(shù)學成績,結果按數(shù)學成績由高到低顯示
操作:
select name,math from exam_result where name like '孫%' or name like '曹%' order by math desc;
如圖:

2.4.篩選
語法:
起始下標為 0 -- 從 0 開始,篩選 n 條結果 SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n; 從 s 開始,篩選 n 條結果 SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT s, n; 從 s 開始,篩選 n 條結果,比第二種用法更明確,建議使用 SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n OFFSET s;
操作:
select * from exam_result limit 3;

select * from exam_result limit 3,6; select * from exam_result limit 3,8;

select * from exam_result limit 3 offset 5;

3.更新操作
3.1.update
update用于修改表中已經(jīng)存在的數(shù)據(jù)。
基本語法:
update 表名 set 字段名1 = 新值1,字段名2 = 新值2,... [where 篩選條件] [order by 排序字段] [limit 更新數(shù)量];
3.2.實例
<1>.將孫悟空同學的數(shù)學成績變更為 90 分
先查看原數(shù)據(jù) ,操作:
select name, math from exam_result where name = '孫悟空';

進行更新操作:
update exam_result set math=90 where name='孫悟空';

<2>.將曹孟德同學的數(shù)學成績變更為 60 分,語文成績變更為 70 分
update exam_result set math=60,chinese=70 where name='曹孟德'; select name, math,chinese from exam_result where name = '曹孟德';
如圖:

<3>.將總成績倒數(shù)前三的 3 位同學的數(shù)學成績加上 30 分
先查詢表數(shù)據(jù),操作:
select name, math, chinese + math + english 總分 from exam_result order by 總分 limit 3;

update exam_result set math=math+30 order by math+chinese+english limit 3;

注意:mysql不支持 math += 30 這種語法
<4>.將所有同學的語文成績更新為原來的 2 倍
注意:更新全表的語句要慎用?。。?/p>
查看原數(shù)據(jù),如圖:

操作:
update exam_result set chinese=chinese*2;

4.刪除操作
注意:刪除表數(shù)據(jù)的操作要慎用
4.1.delete
基本語法
delete from 表名 [where 篩選條件] [order by 排序字段] [limit 刪除數(shù)量];
<1>.例如刪除孫悟空同學的考試成績:
select name from exam_result where name='孫悟空';

delete from exam_result where name = '孫悟空'; select name from exam_result where name='孫悟空';

<2>.刪除整張表數(shù)據(jù)
準備測試表:
create table for_delete(id int primary key auto_increment, name varchar(20));
插入測試數(shù)據(jù):
insert into for_delete (name) values ('A'), ('B'), ('C');
查看測試數(shù)據(jù):

刪除整表數(shù)據(jù):
delete from for_delete;

查看刪除結果時,可以看出表中的數(shù)據(jù)都被刪除了,但是表沒有被刪除。
再插入一條數(shù)據(jù),自增 id 在原值上增長,
insert into for_delete (name) values ('D');

查看表結構,會有 auto_increment=n 項:

4.2.截斷表
語法:
truncate [table] table_name;
準備測試表+插入測試數(shù)據(jù)+查看測試數(shù)據(jù),操作:
create table for_truncate(id int primary key auto_increment,name varchar(20));
insert into for_truncate (name) values ('A'),('B'),('C');
select * from for_truncate;
截斷整表數(shù)據(jù),操作:
truncate for_truncate;
查看刪除結果:
select * from for_truncate;

再插入一條數(shù)據(jù),
insert into for_truncate (name) values ('D');
查表,
select * from for_truncate;

查看表結構,
show create table for_truncate\G;

特點:
- 只能清空整張表,不能通過
where刪除部分數(shù)據(jù)。 - 保留表結構,只清空數(shù)據(jù),不會刪除表的字段、約束和索引等結構。
- 執(zhí)行速度較快,
truncate通常不會像delete一樣逐行刪除數(shù)據(jù),因此清空大表時速度更快。 - 重置自增長值,執(zhí)行后,
auto_increment計數(shù)器通常會重新開始。
5.聚合函數(shù)
5.1.函數(shù)
| 函數(shù) | 說明 |
| count(expr) | 返回查詢到的數(shù)據(jù)的 數(shù)量 |
| sum(expr) | 返回查詢到的數(shù)據(jù)的 總和,不是數(shù)字沒有意義 |
| avg(expr) | 返回查詢到的數(shù)據(jù)的 平均值,不是數(shù)字沒有意義 |
| max(expr) | 返回查詢到的數(shù)據(jù)的 最大值,不是數(shù)字沒有意義 |
| min(expr) | 返回查詢到的數(shù)據(jù)的 最小值,不是數(shù)字沒有意義 |
5.2.案例
<1>.統(tǒng)計班級共有多少同學
我們可以使用 * 做統(tǒng)計,不受 NULL 影響,操作:
select count(*) from exam_result;

<2>.統(tǒng)計班級收集的 qq 號有多少

注意:null 不會計入結果
select count(qq) from students;

<3>.統(tǒng)計本次考試的數(shù)學成績分數(shù)個數(shù)
使用count統(tǒng)計全部成績,操作:
select count(math) from exam_result;

count(distinct math) 統(tǒng)計的是去重成績數(shù)量,操作:
select count(distinct math) from exam_result;

<4>.統(tǒng)計數(shù)學成績總分
操作:
select sum(math) from exam_result;

加上一個分數(shù) < 60 的條件,操作:
select sum(math) from exam_result where math<60;

<5>.統(tǒng)計平均總分
select avg(math+chinese+english) from exam_result;

<6>.返回英語最高分
select max(english) from exam_result;

<7>.返回 > 70 分以上的數(shù)學最低分
select min(math) from exam_result where math>70;

5.3.group by
語法:
select column1, column2, .. from table group by column;
案例:
先創(chuàng)建表:
-- 創(chuàng)建dept部門表
create table dep (
deptno int primary key,
dname varchar(20),
loc varchar(20)
);
-- 創(chuàng)建salgrade工資等級表
create table salgrade(
grade int primary key,
losal decimal(7, 2),
hisal decimal(7, 2)
);
-- 創(chuàng)建emp員工表
create table emp(
empno int primary key,
ename varchar(20),
job varchar(20),
mgr int,
hiredate date,
sal decimal(7, 2),
comm decimal(7, 2),
deptno int,
constraint fk_emp_dept
foreign key (deptno) references dept(deptno)
);然后再插入數(shù)據(jù):
//向dept部門表插入數(shù)據(jù) insert into dept (deptno, dname, loc) values (10, 'accounting', 'new york'), (20, 'research', 'dallas'), (30, 'sales', 'chicago'), (40, 'operations', 'boston'); //向salgrade工資等級表插入數(shù)據(jù) insert into salgrade (grade, losal, hisal) values (1, 700, 1200), (2, 1201, 1400), (3, 1401, 2000), (4, 2001, 3000), (5, 3001, 9999); //向emp員工表插入數(shù)據(jù) insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7369, 'smith', 'clerk', 7902, '1980-12-17', 800, null, 20), (7499, 'allen', 'salesman', 7698, '1981-02-20', 1600, 300, 30), (7521, 'ward', 'salesman', 7698, '1981-02-22', 1250, 500, 30), (7566, 'jones', 'manager', 7839, '1981-04-02', 2975, null, 20), (7654, 'martin', 'salesman', 7698, '1981-09-28', 1250, 1400, 30), (7698, 'blake', 'manager', 7839, '1981-05-01', 2850, null, 30), (7782, 'clark', 'manager', 7839, '1981-06-09', 2450, null, 10), (7788, 'scott', 'analyst', 7566, '1987-04-19', 3000, null, 20), (7839, 'king', 'president', null, '1981-11-17', 5000, null, 10), (7844, 'turner', 'salesman', 7698, '1981-09-08', 1500, 0, 30), (7876, 'adams', 'clerk', 7788, '1987-05-23', 1100, null, 20), (7900, 'james', 'clerk', 7698, '1981-12-03', 950, null, 30), (7902, 'ford', 'analyst', 7566, '1981-12-03', 3000, null, 20), (7934, 'miller', 'clerk', 7782, '1982-01-23', 1300, null, 10);
<1>.顯示每個部門的平均工資和最高工資
select deptno,avg(sal) as 平均工資,max(sal) as 最高工資 from emp group by deptno;
執(zhí)行結果:

這里按照 deptno分組,然后分別計算每個部門的平均工資和最高工資。
<2>. 顯示每個部門中每種崗位的平均工資和最低工資,
select deptno,job,avg(sal) as 平均工資,min(sal) as 最低工資 from emp group by deptno, job;
這里按照兩個字段進行分組:
group by deptno, job
只有部門編號和崗位都相同的員工,才會被劃分到同一組。
執(zhí)行結果:

<3>. 統(tǒng)計各個部門的平均工資
select deptno,avg(sal) as 平均工資 from emp group by deptno;

此時只進行分組統(tǒng)計,還沒有對分組結果進行篩選。
<4>. 顯示平均工資低于2000的部門及其平均工資
需要使用 having對 group by產(chǎn)生的分組結果進行過濾
select deptno,avg(sal) as 平均工資 from emp group by deptno having 平均工資 < 2000;
也可以不使用別名:
select deptno,avg(sal) as 平均工資 from emp group by deptno having avg(sal) < 2000;
執(zhí)行結果:

那如果我們使用where呢?操作:
select deptno,avg(sal) as 平均工資 from emp group by deptno where avg(sal) < 2000;

報錯原因:
where必須寫在 group by之前,SQL一般書寫順序是:
select → from → where → group by → having → order by
那如果這樣寫呢?
select deptno,avg(sal) as 平均工資 from emp where avg(sal)<2000 group by deptno;

報錯原因:where不能篩選聚合結果,avg(sal)是分組后才計算出來的平均工資,而 where在分組前執(zhí)行,所以 where不能使用 avg()等聚合函數(shù)。
having的執(zhí)行順序:
from emp
↓
group by deptno
↓
計算avg(sal),產(chǎn)生平均工資
↓
having 平均工資 < 2000
↓
select返回結果where的執(zhí)行順序:
from emp
↓
where sal < 2000
篩選出工資低于2000的員工
↓
group by deptno
按照部門編號進行分組
↓
計算每個部門的avg(sal)
↓
select deptno, avg(sal) as 平均工資
↓
返回查詢結果總結:
本篇介紹了 MySQL 中數(shù)據(jù)的增刪改查操作,并學習了 where、order by和 limit等常用查詢子句。通過聚合函數(shù)、group by和 having,可以進一步完成數(shù)據(jù)統(tǒng)計、分組以及分組結果篩選。掌握這些基礎語法和執(zhí)行順序后,就能夠根據(jù)實際需求組合出較為完整的數(shù)據(jù)查詢語句。
到此這篇關于MySQL數(shù)據(jù)庫原理與實踐指南之基本查詢的文章就介紹到這了,更多相關mysql數(shù)據(jù)庫原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
關于MySQL性能調(diào)優(yōu)你必須了解的15個重要變量(小結)
MYSQL 應該是比較流行的 WEB 后端數(shù)據(jù)庫。雖然 NOSQL 最近越來越多的被提到,但是相信大部分架構師還是會選擇 MYSQL 來做數(shù)據(jù)存儲。本文作者總結梳理MySQL性能調(diào)優(yōu)的15個重要變量,感興趣的可以了解一下2019-07-07
MySQL數(shù)據(jù)庫優(yōu)化技術之索引使用技巧總結
這篇文章主要介紹了MySQL數(shù)據(jù)庫優(yōu)化技術之索引使用方法,結合實例形式總結分析了MySQL表的優(yōu)化、索引設置、SQL優(yōu)化等相關技巧,非常具有實用價值,需要的朋友可以參考下2016-07-07

