MySQL表聚合與聯(lián)合查詢的實(shí)現(xiàn)
一. 聚合查詢
1.1 聚合函數(shù)
一般情況下,我們需要的聚合數(shù)據(jù)(總和,平均數(shù),最大最小值等)并不總是存儲(chǔ)在表中。 但是,可以通過執(zhí)行存儲(chǔ)數(shù)據(jù)的計(jì)算來獲取它。
MySQL提供了許多聚合函數(shù),包括AVG
,COUNT
,SUM
,MIN
,MAX
等。除COUNT
函數(shù)外,其它聚合函數(shù)在執(zhí)行計(jì)算時(shí)會(huì)忽略NULL
值 , 同時(shí) , 聚合函數(shù)不允許嵌套使用 .
函數(shù) | 說明 |
---|---|
count(列名或表達(dá)式) | 返回查詢到的數(shù)據(jù)的個(gè)數(shù) |
sum(列名或表達(dá)式) | 返回查詢到的數(shù)據(jù)的和, (不是數(shù)字沒有意義) |
avg(列名或表達(dá)式) | 返回查詢到的數(shù)據(jù)的平均值 |
max(列名或表達(dá)式) | 返回查詢到的數(shù)據(jù)的最大值 |
min(列名或表達(dá)式) | 返回查詢到的數(shù)據(jù)的最小值 |
以上的聚合函數(shù)可以在列名和表達(dá)式之前加上
distinct
, 先對(duì)查詢到的數(shù)據(jù)進(jìn)行去重, 再進(jìn)行計(jì)算
下面,我們將創(chuàng)建一組示例數(shù)據(jù),對(duì)以上的聚合函數(shù)進(jìn)行演示,
--- 創(chuàng)建學(xué)生成績表 mysql> create table exam( -> id int primary key comment '學(xué)號(hào)', -> name varchar(20) comment '學(xué)生姓名', -> email varchar(50) not null comment '電子郵箱', -> chinese decimal(4,1) comment '語文成績', -> english decimal(4,1) comment '英語成績', -> math decimal(4,1) comment'數(shù)學(xué)成績' -> ); Query OK, 0 rows affected (0.02 sec) --- 插入學(xué)生成績數(shù)據(jù) mysql> insert into exam values(202301,'張華','123452@163.com',69,112,110), -> (202302,'李三','1452563@163.com',115.5,120,89), -> (202303,'宋七','36215465@qq.com',110,113,66), -> (202304,'王五','15547522@163.com',89,65,78), -> (202305,'趙四','15623355@163.com',90,112,130), -> (202306,'李八','18625222@163.com',null,null,null); Query OK, 6 rows affected (0.01 sec) Records: 6 Duplicates: 0 Warnings: 0 ---學(xué)生成績表結(jié)構(gòu) mysql> desc exam; +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(20) | YES | | NULL | | | email | varchar(50) | NO | | NULL | | | chinese | decimal(4,1) | YES | | NULL | | | english | decimal(4,1) | YES | | NULL | | | math | decimal(4,1) | YES | | NULL | | +---------+--------------+------+-----+---------+-------+ 6 rows in set (0.00 sec) --- 數(shù)據(jù)詳表 mysql> select * from exam; +--------+------+------------------+---------+---------+-------+ | id | name | email | chinese | english | math | +--------+------+------------------+---------+---------+-------+ | 202301 | 張華 | 123452@163.com | 69.0 | 112.0 | 110.0 | | 202302 | 李三 | 1452563@163.com | 115.5 | 120.0 | 89.0 | | 202303 | 宋七 | 36215465@qq.com | 110.0 | 113.0 | 66.0 | | 202304 | 王五 | 15547522@163.com | 89.0 | 65.0 | 78.0 | | 202305 | 趙四 | 15623355@163.com | 90.0 | 112.0 | 130.0 | | 202306 | 李八 | 18625222@163.com | NULL | NULL | NULL | +--------+------+------------------+---------+---------+-------+ 6 rows in set (0.01 sec)
count()
函數(shù)
使用 count()
函數(shù) 可以返回?cái)?shù)據(jù)表中的行數(shù) , 允許對(duì)表中所有符合特定條件的所有行進(jìn)行計(jì)數(shù) .
#計(jì)算表中的總行數(shù) mysql> select count(*) from exam; +----------+ | count(*) | +----------+ | 6 | +----------+ 1 row in set (0.01 sec #計(jì)算表中chinese中的總行數(shù) mysql> select count(math) from exam; +-------------+ | count(math) | +-------------+ | 5 | +-------------+ 1 row in set (0.00 sec) #計(jì)算表中english列的總行數(shù),并去重 mysql> select count(distinct english) from exam; +-------------------------+ | count(distinct english) | +-------------------------+ | 4 | +-------------------------+ 1 row in set (0.01 sec)
COUNT(*)
函數(shù)計(jì)算包含NULL
和非NULL
值的行,即:所有行 , 而count (列名) 進(jìn)行計(jì)算時(shí) , 不會(huì)將值為NULL
的行計(jì)算在內(nèi), 即所有的非空行 . count(distinct 列名) 則會(huì)返回不包含空值的唯一行數(shù) .
結(jié)合where語句進(jìn)行使用
#查詢exam表當(dāng)中, 英語成績?yōu)?12的人數(shù) mysql> select count(english) from exam where english = 112; +----------------+ | count(english) | +----------------+ | 2 | +----------------+ 1 row in set (0.00 sec)
sum()
函數(shù)
SUM()函數(shù)返回一組值的總和,SUM()函數(shù)忽略NULL
值。如果找不到匹配行,則SUM()函數(shù)返回NULL
值。
#計(jì)算數(shù)學(xué)成績的總和, 并命名為emath mysql> select sum(math) as emath from exam; +-------+ | emath | +-------+ | 473.0 | +-------+ 1 row in set (0.00 sec) #計(jì)算英語成績低于120分的成績總和 mysql> select sum(english) from exam where english < 120; +--------------+ | sum(english) | +--------------+ | 402.0 | +--------------+ 1 row in set (0.00 sec)
avg()
函數(shù)
AVG()函數(shù)計(jì)算一組值的平均值。 它計(jì)算過程中是忽略NULL
值的 , 使用 avg()
函數(shù)可以的到 一組數(shù)據(jù)的平均值 .
# 計(jì)算所有同學(xué)的語文成績的平均值 mysql> select avg(chinese) from exam; +--------------+ | avg(chinese) | +--------------+ | 94.70000 | +--------------+ 1 row in set (0.03 sec) #計(jì)算總分的平均分 mysql> select avg(math+chinese+english) as 總均分 from exam; +-----------+ | 總均分 | +-----------+ | 293.70000 | +-----------+ 1 row in set (0.00 sec)
MAX()
函數(shù)
MAX()
函數(shù)返回一組值中的最大值。MAX()
函數(shù)在許多查詢中非常方便,例如查找最大數(shù)量,最昂貴的產(chǎn)品以及客戶的最大付款數(shù)等 .
# 查詢總分最高的同學(xué)總分 mysql> select max(math+english+chinese) as 總成績 from exam; +--------+ | 總成績 | +--------+ | 332.0 | +--------+ 1 row in set (0.00 sec) #查詢單科英語成績的最高分的姓名 mysql> select max(english) from exam; +--------------+ | max(english) | +--------------+ | 120.0 | +--------------+ 1 row in set (0.00 sec)
不使用
max()
函數(shù)的情況 , 也可以使用order by
對(duì)數(shù)據(jù)集進(jìn)行降序,并使用limit
字句對(duì)結(jié)果集進(jìn)行降序排序
mysql> select (chinese+math+english) as total from exam order by total desc limit 1; +-------+ | total | +-------+ | 332.0 | +-------+ 1 row in set (0.00 sec)
如果要找到總成績最高的同學(xué)的全部信息 , 需要使用子查詢進(jìn)行
# 查詢總成績最高的同學(xué)信息 mysql> select * -> from exam -> where chinese+math+english = (select max(chinese+math+english) -> from exam -> ); +--------+------+------------------+---------+---------+-------+ | id | name | email | chinese | english | math | +--------+------+------------------+---------+---------+-------+ | 202305 | 趙四 | 15623355@163.com | 90.0 | 112.0 | 130.0 | +--------+------+------------------+---------+---------+-------+ 1 row in set (0.00 sec)
Min()
函數(shù)
Min()
函數(shù)用于返回一組值當(dāng)中的最小值 , 通常用于 查詢一組數(shù)據(jù)當(dāng)中最小的值 , 如 最小單價(jià), 最小分?jǐn)?shù) 等 , 和 max() 函數(shù)的用法類似 。
# 查詢最小的總分 mysql> select min(math + english + chinese) as total from exam; +-------+ | total | +-------+ | 232.0 | +-------+ 1 row in set (0.00 sec) #查詢最小總分的全部信息 mysql> select * from exam where chinese+english+math = (select min(math + english + chinese) as total from exam); +--------+------+------------------+---------+---------+------+ | id | name | email | chinese | english | math | +--------+------+------------------+---------+---------+------+ | 202304 | 王五 | 15547522@163.com | 89.0 | 65.0 | 78.0 | +--------+------+------------------+---------+---------+------+ 1 row in set (0.00 sec)
MySQL 當(dāng)中除了一些常用的聚合函數(shù)外 , 還包括一些字符串函數(shù) , 日期時(shí)間函數(shù) , 控制流函數(shù)等 , 下面再列舉一些比較常見的其他函數(shù) .
IFNULL
函數(shù)
IFNULL
函數(shù) 是MySQL控制流函數(shù)之一,它接受兩個(gè)參數(shù) , 如果不是 NULL ,則返回第一個(gè)參數(shù),否則IFNULL
函數(shù) 返回第二個(gè)參數(shù)
IFNULL(expression_1,expression_2);
如果expression_1
不為NULL
,則IFNULL
函數(shù)返回expression_1
; 否則返回expression_2
的結(jié)果。
示例表如下所示:
#查找某位同學(xué)的聯(lián)系方式 (如果電話為空,使用郵箱) mysql> select name,ifnull(phone,email) as 聯(lián)系方式 from exam; +------+------------------+ | name | 聯(lián)系方式 | +------+------------------+ | 張華 | 13225631456 | | 李三 | 15698475235 | | 宋七 | 15236486952 | | 王五 | 15547522@163.com | | 趙四 | 13562698745 | | 李八 | 18625222@163.com | +------+------------------+ 6 rows in set (0.00 sec) #其中,王五和李八的電話為空,則使用其電子郵箱作為其聯(lián)系方式。
- 日期、時(shí)間函數(shù)
now()函數(shù) | 返回當(dāng)前日期和時(shí)間。 |
---|---|
month()函數(shù) | 返回一個(gè)表示指定日期的月份的整數(shù)。 |
year()函數(shù) | 返回日期值的年份部分。 |
dayname()函數(shù) | 獲取指定日期的工作日的名稱。 |
round(數(shù)據(jù),n) 函數(shù) | 表示返回的數(shù)據(jù)保留n位小數(shù) |
mysql> select year('2018-01-01'); +--------------------+ | year('2018-01-01') | +--------------------+ | 2018 | +--------------------+ 1 row in set mysql> select dayname('2018-01-01') dayname; +---------+ | dayname | +---------+ | Monday | +---------+ 1 row in set
1.2 GROUP BY子句
GROUP BY
子句通過列或表達(dá)式的值將一組行分組為一個(gè)小分組的匯總行記錄。GROUP BY
子句為每個(gè)分組返回一行。換句話說,它減少了結(jié)果集中的行數(shù),當(dāng)GROUP BY
子句與聚合函數(shù)相結(jié)合時(shí), 可以返回每個(gè)分組的單個(gè)值。
#示例職工表 mysql> create table emp( -> id int primary key auto_increment, -> name varchar(20) not null, -> role varchar(20) not null, -> salary numeric(11,2) -> ); Query OK, 0 rows affected (0.05 sec) mysql> insert into emp(name, role, salary) values -> ('張三','科員', 2000.54), -> ('宋七','副廳', 8996.99), -> ('趙四','科員', 1800.11), -> ('李八','科長', 4540.5), -> ('宋九','科員', 2356.33); Query OK, 5 rows affected (0.01 sec) Records: 5 Duplicates: 0 Warnings: 0 mysql> select * from emp; +----+------+------+---------+ | id | name | role | salary | +----+------+------+---------+ | 1 | 張三 | 科員 | 2000.54 | | 2 | 宋七 | 副廳 | 8996.99 | | 3 | 趙四 | 科員 | 1800.11 | | 4 | 李八 | 科長 | 4540.50 | | 5 | 宋九 | 科員 | 2356.33 | +----+------+------+---------+ 5 rows in set (0.00 sec)
對(duì)職工表進(jìn)行分組查詢 , 查詢已知數(shù)據(jù)當(dāng)中每個(gè)職位的最低和最高工資
mysql> select role,max(salary),min(salary) from emp group by role; +------+-------------+-------------+ | role | max(salary) | min(salary) | +------+-------------+-------------+ | 副廳 | 8996.99 | 8996.99 | | 科員 | 2356.33 | 1800.11 | | 科長 | 4540.50 | 4540.50 | +------+-------------+-------------+ 3 rows in set (0.00 sec)
1.3 HAVING子句
GROUP BY
子句進(jìn)行分組以后,需要對(duì)分組結(jié)果再進(jìn)行條件過濾時(shí),不能使用 WHERE 語句,而需要使用HAVING
子句
再次對(duì)上述的職工表進(jìn)行操作,找出最高工資大于4000的職工職位角色和工資
mysql> select role,max(salary) from emp group by role having max(salary) > 4000; +------+-------------+ | role | max(salary) | +------+-------------+ | 副廳 | 8996.99 | | 科長 | 4540.50 | +------+-------------+ 2 rows in set (0.00 sec)
條件篩選可以使用where, order by, limit等來實(shí)現(xiàn),也可以不使用
HAVING
子句和where
語句的使用區(qū)別
- 分組之前指定條件, 也就是先篩選再分組, 使用
where
關(guān)鍵字. - 分組之后指定條件, 也就是先分組再篩選, 使用
group by
關(guān)鍵字
where
和group by
語法上要注意區(qū)分, where
語句緊跟在表名后, 而having
跟在group by
后 .
示例:查詢工資小于5000的職工中,各職工角色的平均工資(保留兩位小數(shù))
mysql> select role,round(avg(salary)) from emp where salary < 5000 group by role; +------+--------------------+ | role | round(avg(salary)) | +------+--------------------+ | 科員 | 2052 | | 科長 | 4541 | +------+--------------------+ 2 rows in set (0.01 sec)
二 . 多表關(guān)系
- 概述
? 項(xiàng)目開發(fā)當(dāng)中,在進(jìn)行數(shù)據(jù)庫的表結(jié)構(gòu)設(shè)計(jì)時(shí),會(huì)根據(jù)業(yè)務(wù)需求和業(yè)務(wù)模塊之間的關(guān)系,分析并設(shè)計(jì)表結(jié)構(gòu),由于業(yè)務(wù)之間相互關(guān)聯(lián),所以各個(gè)表結(jié)構(gòu)之間也存在著某種聯(lián)系 , 基本上分為三種: 一對(duì)多/多對(duì)多/一對(duì)一.
- 一對(duì)多(多對(duì)一)
案例 : 班級(jí)與學(xué)生的關(guān)系
關(guān)系 : 一個(gè)班級(jí)擁有多個(gè)學(xué)生 , 一個(gè)學(xué)生屬于一個(gè)班級(jí)
實(shí)現(xiàn) : 在多的 一方(學(xué)生) 建立外鍵, 指向另一方的主鍵
- 多對(duì)多
案例 : 學(xué)生與課程的關(guān)系
關(guān)系 :一名學(xué)生可以選修多門課程 , 一門課程也可以供多個(gè)學(xué)生來選擇 .
實(shí)現(xiàn) : 建立第三張中間表, 中間表中至少包含兩個(gè)外鍵,分別關(guān)聯(lián)兩表的主鍵
- 一對(duì)一
案例 : 用戶與用戶詳情之間的關(guān)系
關(guān)系 : 多用于單表拆分 , 將一張表的基礎(chǔ)字段放在一張表當(dāng)中 , 其他詳情字段放在另一張表當(dāng)中,以提升操作效率
實(shí)現(xiàn) : 在任意一方加入外鍵,關(guān)聯(lián)另一方的主鍵 , 并設(shè)置外鍵是唯一的
三、聯(lián)合查詢
實(shí)際開發(fā)當(dāng)中往往要使用多個(gè)表的的數(shù)據(jù),所以需要多表聯(lián)合查詢 , 多表聯(lián)合查詢時(shí)是對(duì)多張表的數(shù)據(jù)取笛卡爾積 , 然后對(duì)聯(lián)合表中篩選出需要的數(shù)據(jù)
對(duì)n條記錄的表A和m條記錄的表B進(jìn)行笛卡爾積,一共會(huì)產(chǎn)生n*m
條記錄, 當(dāng)兩張表的數(shù)據(jù)量很大的時(shí)候, 這個(gè)操作就非常危險(xiǎn)了 , 需要慎重使用
mysql> select * from class; +----------+------------+ | id | name | +----------+------------+ | 1 | 計(jì)科1班 | | 2 | 計(jì)科2班 | +----------+------------+ 2 rows in set (0.00 sec) mysql> select * from student; +------+--------+----------+ | id | name | class_id | +------+--------+----------+ | 1 | 張三 | 1 | | 2 | 李四 | 1 | | 3 | 王五 | 2 | | 4 | 趙六 | 2 | +------+--------+----------+ #兩個(gè)表進(jìn)行笛卡爾集之后可以得到結(jié)果 mysql> select * from student, class; +------+--------+----------+----------+------------+ | id | name | class_id | id | name | +------+--------+----------+----------+------------+ | 1 | 張三 | 1 | 1 | 計(jì)科1班 | | 1 | 張三 | 1 | 2 | 計(jì)科2班 | | 2 | 李四 | 1 | 1 | 計(jì)科1班 | | 2 | 李四 | 1 | 2 | 計(jì)科2班 | | 3 | 王五 | 2 | 1 | 計(jì)科1班 | | 3 | 王五 | 2 | 2 | 計(jì)科2班 | | 4 | 趙六 | 2 | 1 | 計(jì)科1班 | | 4 | 趙六 | 2 | 2 | 計(jì)科2班 | +------+--------+----------+----------+------------+ 8 rows in set (0.00 sec)
上述兩表進(jìn)行笛卡爾集之后 , 得到了 4 * 2 即 8 條的結(jié)果 , 在這之中只有class_id相同的數(shù)據(jù)才是有效數(shù)據(jù) , 所以要添加限制條件 才能篩選出有效數(shù)據(jù)
3.1 內(nèi)連接
內(nèi)連接查詢的是兩張表交集的部分
- 隱式內(nèi)連接
select 字段列表 from 表1 ,表2 where ... = .. .;
- 顯式內(nèi)連接
select 字段列表 from 表1 inner join 表2 on 連接條件
以上述兩張學(xué)生表和課程表為例 , 查詢一名學(xué)生的姓名 , 以及該學(xué)生所在的班級(jí)名稱
#隱式內(nèi)連接 mysql> select student.name, class.name from class,student -> where student.class_id = class.id; +------+---------+ | name | name | +------+---------+ | 張三 | 計(jì)科1班 | | 李四 | 計(jì)科1班 | | 王五 | 計(jì)科2班 | | 趙六 | 計(jì)科2班 | +------+---------+ 4 rows in set (0.01 sec) # 也可以對(duì)表名起一個(gè)別名 mysql> select s.name, c.name from class c,student s -> where s.class_id = c.id; +------+---------+ | name | name | +------+---------+ | 張三 | 計(jì)科1班 | | 李四 | 計(jì)科1班 | | 王五 | 計(jì)科2班 | | 趙六 | 計(jì)科2班 | +------+---------+ 4 rows in set (0.00 sec) #顯式內(nèi)連接 mysql> select student.name, class.name from student inner join class on student.class_id = class.id; +------+---------+ | name | name | +------+---------+ | 張三 | 計(jì)科1班 | | 李四 | 計(jì)科1班 | | 王五 | 計(jì)科2班 | | 趙六 | 計(jì)科2班 | +------+---------+ 4 rows in set (0.03 sec)
3.2 外連接
- 左外連接
相當(dāng)于查詢表1(左表)所有的數(shù)據(jù)包含表1和表2交集部分的數(shù)據(jù)
select 字段列表 from 表1 left join 表2 on 條件 ... ;
- 右外連接
相當(dāng)于查詢表2(右表)的所有數(shù)據(jù) , 包含表1 和表2 交集部分的數(shù)據(jù)
select 字段列表 from 表1 right join 表2 on 條件 ....;
示例:
#表結(jié)構(gòu)如下所示 mysql> select * from class; +----+---------+ | id | name | +----+---------+ | 1 | 計(jì)科1班 | | 2 | 計(jì)科2班 | | 3 | NULL | +----+---------+ 3 rows in set (0.00 sec) mysql> select * from student; +----+------+----------+ | id | name | class_id | +----+------+----------+ | 1 | 張三 | 1 | | 2 | 李四 | 1 | | 3 | 王五 | 2 | | 4 | 趙六 | 2 | | 5 | 宋六 | NULL | +----+------+----------+ 5 rows in set (0.01 sec) mysql> select * from student left join class on student.class_id = class.id; +----+------+----------+------+---------+ | id | name | class_id | id | name | +----+------+----------+------+---------+ | 1 | 張三 | 1 | 1 | 計(jì)科1班 | | 2 | 李四 | 1 | 1 | 計(jì)科1班 | | 3 | 王五 | 2 | 2 | 計(jì)科2班 | | 4 | 趙六 | 2 | 2 | 計(jì)科2班 | | 5 | 宋六 | NULL | NULL | NULL | +----+------+----------+------+---------+ 5 rows in set (0.00 sec) mysql> select * from class left join student on class.id = student.class_id; +----+---------+------+------+----------+ | id | name | id | name | class_id | +----+---------+------+------+----------+ | 1 | 計(jì)科1班 | 1 | 張三 | 1 | | 1 | 計(jì)科1班 | 2 | 李四 | 1 | | 2 | 計(jì)科2班 | 3 | 王五 | 2 | | 2 | 計(jì)科2班 | 4 | 趙六 | 2 | | 3 | NULL | NULL | NULL | NULL | +----+---------+------+------+----------+ 5 rows in set (0.00 sec) #使用左外連接或者右外連接的前提一般是 , 需求的列中部分元素為空值,直接使用內(nèi)連接無法顯示出來,所以采用左外連接或者 右外連接
3.3 自連接
自連接指的是在同一張表內(nèi)連接自身進(jìn)行查詢 ,自連接查詢可以是內(nèi)連接查詢也可以是外連接查詢 . (自連接查詢中表必需起別名)
select 字段列表 from 表A 別名A join 表A 別名B on 條件
案例 : 員工表中包含以下字段 : 員工 id , 員工姓名 name,員工年齡 age , 員工領(lǐng)導(dǎo)managerid
# 查詢員工以及所屬領(lǐng)導(dǎo)的名稱 (內(nèi)) select a.name,b.name from emp a,emp b where a.managerid = b.id; (查詢的結(jié)果不包含領(lǐng)導(dǎo)為null的字段) # 查詢所有員工及其領(lǐng)導(dǎo)的名字 , 如果員工沒有領(lǐng)導(dǎo), 也需要查詢出來 select a.name '員工',b.name '領(lǐng)導(dǎo)' from emp a left join emp b on a.managerid = b.id; #使用左外連接會(huì)將所有員工的姓名全部顯示出來, 包括沒有領(lǐng)導(dǎo)的
3.4 合并查詢
在實(shí)際應(yīng)用中,為了合并多個(gè)select的執(zhí)行結(jié)果,可以使用集合操作符 union,union all。使用UNION和UNION ALL時(shí),前后查詢的結(jié)果集中,字段需要一致。
union all
該操作符用于取得兩個(gè)結(jié)果集的并集。當(dāng)使用該操作符時(shí),不會(huì)去掉結(jié)果集中的重復(fù)行(合并后的結(jié)果中包含重復(fù)行)
select * from course where id<3 union all select * from course where name= '數(shù)據(jù)結(jié)構(gòu)'; # 當(dāng)查詢字段不一致時(shí)會(huì)報(bào)錯(cuò)
union
該操作符用于取得兩個(gè)結(jié)果集的并集。當(dāng)使用該操作符時(shí),會(huì)自動(dòng)去掉結(jié)果集中的重復(fù)行
select * from course where id<3 union select * from course where name= '數(shù)據(jù)結(jié)構(gòu)';
同理 or
select * from course where id < 3 or name = '數(shù)據(jù)結(jié)構(gòu)';
union查詢時(shí),在索引列查詢速度快,or,in采用的是全表掃描機(jī)制更適用于非索引列查找。
3.4 子查詢
- 概念 : SQL語句中嵌套select語句 , 稱為嵌套查詢 , 又稱子查詢 .
select * from table1 where column1 = (select column1 fropm table2);
子查詢外部的語句可以是 : INSERT / UPDATE / SELECT 中的任何一個(gè)
- 標(biāo)量子查詢
子查詢返回的結(jié)果為單個(gè)值(數(shù)字,字符串,日期)等, 常用操作符: = <> > >= < <=
#查詢張三同學(xué)的同班同學(xué) select * from student where class_id =(select class_id from student where name = '張三');
- 列子查詢
子查詢返回的結(jié)果是 一列(可以是多行) ,這種子查詢稱為列子查詢 .
常用的操作符為 : IN , NOT IN , ANY ,ALL
# 查詢選修課程名稱為語文或者英語的分?jǐn)?shù)信息 (in) select * from score where course_id in (select id from course where name='語文' or name='英文'); #查詢語文課程分?jǐn)?shù)大于其他任意一名學(xué)生的信息(any) select * from score where grade>any(select grade from score where course_id = (select class_id from student where name = '語文'));
- exists關(guān)鍵字
exists( )內(nèi)子查詢語句返回結(jié)果不為空,說明where條件成立就會(huì)執(zhí)行主sql語句。如果為空就表示where條件不成立,sql語句就不會(huì)執(zhí)行。not exists 和 exists相反,子查詢語句結(jié)果為空,則表示where條件成立,執(zhí)行sql語句。否則不執(zhí)行。
- 在from子句中使用子查詢:子查詢語句出現(xiàn)在from子句中。這里要用到數(shù)據(jù)查詢的技巧,把一個(gè)子查詢當(dāng)做一個(gè)臨時(shí)表使用
-- 獲取“計(jì)算機(jī)1班”的平均分,將其看作臨時(shí)表 select avg( sco.score ) score from score sco join student stu ON sco.student_id = stu.id join classes cls ON stu.classes_id = cls.id where cls.NAME = '計(jì)算機(jī)1班';
到此這篇關(guān)于MySQL表聚合與聯(lián)合查詢的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)MySQL聚合與聯(lián)合查詢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
10個(gè)MySQL性能調(diào)優(yōu)的方法
本文介紹了10個(gè)MySQL性能調(diào)優(yōu)的方法,每個(gè)方法的講解都很細(xì)致,非常實(shí)用,,需要的朋友可以參考下2015-07-07windows10系統(tǒng)安裝mysql-8.0.13(zip安裝) 的教程詳解
這篇文章主要介紹了windows10安裝mysql-8.0.13(zip安裝) 的教程,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11mysql 1130錯(cuò)誤,無法登錄遠(yuǎn)程服務(wù)的解決
這篇文章主要介紹了mysql 1130錯(cuò)誤,無法登錄遠(yuǎn)程服務(wù)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03Navicat 遠(yuǎn)程連接 MySQL實(shí)現(xiàn)步驟解析
這篇文章主要介紹了Navicat 遠(yuǎn)程連接 MySQL實(shí)現(xiàn)步驟解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08Windows下mysql community server 8.0.16安裝配置方法圖文教程
這篇文章主要為大家詳細(xì)介紹了Windows下mysql community server 8.0.16安裝配置方法圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-06-06