MySQL 高級查詢

我們使用SQL查詢不能只使用很簡單譬猫、最基礎(chǔ)的SELECT語句查詢移怯。如果想從多個(gè)表查詢比較復(fù)雜的信息,就會(huì)使用高級查詢實(shí)現(xiàn)和橙。常見的高級查詢包括多表連接查詢、內(nèi)連接查詢造垛、外連接查詢與組合查詢等

以一個(gè)簡單的學(xué)生信息表(學(xué)生ID魔招、學(xué)生姓名、學(xué)生性別)與一個(gè)科目表(科目ID五辽、科目)還有學(xué)生成績表(學(xué)生ID办斑、科目ID、分?jǐn)?shù))為例子

創(chuàng)建表

create table scores(
    id int auto_increment primary key,
    stuid int,
    subid int,
    score decimal(5,2),
);
create table students(
    id int auto_increment primary key,
    sname varchar(20),
    sex char(1)
);

create table subjects(
    id int auto_increment primary key,
    stitle varchar(20)
);

學(xué)生列的數(shù)據(jù)不是在這里新建的杆逗,而應(yīng)該從學(xué)生表引用過來乡翅,關(guān)系也是一條數(shù)據(jù);根據(jù)范式要求應(yīng)該存儲(chǔ)學(xué)生的編號罪郊,而不是學(xué)生的姓名等其它信息
同理蠕蚜,科目表也是關(guān)系列,引用科目表中的數(shù)據(jù)

表關(guān)系

外鍵
思考:怎么保證關(guān)系列數(shù)據(jù)的有效性呢悔橄?任何整數(shù)都可以嗎靶累?
答:必須是學(xué)生表中id列存在的數(shù)據(jù),可以通過外鍵約束進(jìn)行數(shù)據(jù)的有效性驗(yàn)證為stuid添加外鍵約束

alter table scores 
add constraint stu_sco foreign key(stuid) references students(id);

此時(shí)插入或者修改數(shù)據(jù)時(shí)癣疟,如果stuid的值在students表中不存在則會(huì)報(bào)錯(cuò)
在創(chuàng)建表時(shí)可以直接創(chuàng)建約束

外鍵的級聯(lián)操作

  • 在刪除students表的數(shù)據(jù)時(shí)挣柬,如果這個(gè)id值在scores中已經(jīng)存在,則會(huì)拋異常
  • 推薦使用邏輯刪除睛挚,還可以解決這個(gè)問題
  • 可以創(chuàng)建表時(shí)指定級聯(lián)操作邪蛔,也可以在創(chuàng)建表后再修改外鍵的級聯(lián)操作
alter table scores 
add constraint stu_sco foreign key(stuid) references students(id) 
on delete cascade;

在創(chuàng)建表時(shí)可以直接創(chuàng)建約束,添加級聯(lián)操作

create table scores(
    id int auto_increment primary key,
    stuid int,
    subid int,
    score decimal(5,2),
    #這里我在創(chuàng)建表時(shí)直接創(chuàng)建約束扎狱,添加級聯(lián)操作侧到。后面就不用在添加了
    foreign key(stuid) references students(id) on delete cascade,
    foreign key(subid) references subjects(id) on delete cascade
);

級聯(lián)操作的類型包括:
restrict(限制):默認(rèn)值,拋異常
cascade(級聯(lián)):如果主表的記錄刪掉淤击,則從表中相關(guān)聯(lián)的記錄都將被刪除
set null:將外鍵設(shè)置為空
no action:什么都不做

連接查詢

-- 建表和數(shù)據(jù)S
create table students(
    id int auto_increment primary key,
    sname varchar(20)
);

create table subjects(
    id int auto_increment primary key,
    stitle varchar(20)
);
create table scores(
    id int auto_increment primary key,
    stuid int,
    subid int,
    score decimal(5,2),
    foreign key(stuid) references students(id) on delete cascade,
    foreign key(subid) references subjects(id) on delete cascade
);

insert into subjects(stitle) values('語文');
insert into subjects(stitle) values('數(shù)學(xué)');
insert into subjects(stitle) values('英語');

insert into students(sname,sex) values('小明','男');
insert into students(sname,sex) values('小美','女');
insert into students(sname,sex) values('小壯','男');
insert into students(sname,sex) values('小敏','女');

insert into scores(stuid,subid,score) values(1,1,88);
insert into scores(stuid,subid,score) values(1,2,95);
insert into scores(stuid,subid,score) values(2,1,89);
insert into scores(stuid,subid,score) values(2,3,95);
insert into scores(stuid,subid,score) values(3,1,92);
insert into scores(stuid,subid,score) values(3,2,85);
insert into scores(stuid,subid,score) values(4,2,82);
insert into scores(stuid,subid,score) values(4,3,99);
/*查詢學(xué)生的編號床牧,姓名,科目的名稱遭贸,成績*/
select t1.id,t1.sname,t2.stitle,t3.score
from students t1,subjects t2,scores t3
where t3.stuid=t1.id and t3.subid=t2.id;

select t1.id,t1.sname,t2.stitle,t3.score
from scores t3
inner join students t1
on t3.stuid = t1.id 
inner join subjects t2
on t3.subid = t2.id;

內(nèi)連接(INNER JOIN)
   INNER JOIN ...表 ON ...條件

-- 查詢學(xué)生的姓名戈咳、平均分
select students.sname,avg(scores.score)
from scores
inner join students on scores.stuid=students.id
group by students.sname;

/*查詢學(xué)生的編號,姓名,科目的名稱著蛙,成績*/
-- 方法一
select t1.id,t1.sname,t2.stitle,t3.score
from students t1,subjects t2,scores t3
where t3.stuid=t1.id and t3.subid=t2.id;
-- 方法二
select t1.id,t1.sname,t2.stitle,t3.score
from scores t3
inner join students t1
on t3.stuid = t1.id 
inner join subjects t2
on t3.subid = t2.id;
-- 方法三
select t1.id,t1.sname,t2.stitle,t3.score
from  students t1
inner join scores t3
on t3.stuid = t1.id 
inner join subjects t2
on t3.subid = t2.id;

-- 查詢學(xué)生的姓名删铃、平均分
select students.sname,avg(scores.score)
from scores
inner join students on scores.stuid=students.id
group by students.sname;
-- 查詢男生的姓名、總分
select students.sname,sum(scores.score)
from scores
inner join students on scores.stuid=students.id
where students.sex='男'
group by students.sname;
-- 查詢科目的名稱踏堡、平均分
select subjects.stitle,avg(scores.score)
from scores
inner join subjects on scores.subid=subjects.id
group by subjects.stitle;

外聯(lián)結(jié)
1猎唁、左外連接(LEFT OUTER JOIN)
概述:指將左表的所有記錄與右表符合條件的記錄,返回的結(jié)果除內(nèi)連接的結(jié)果顷蟆,還有左表不符合條件的記錄渺氧,并在右表相應(yīng)列中填NULL。
2翩腐、右外連接(RIGHT OUTER JOIN)
概述:與左外連接相反御雕,指將右表的所有記錄與左表符合條件的記錄,返回的結(jié)果除內(nèi)連接的結(jié)果削樊,還有右表不符合條件的記錄豁生,并在左表相應(yīng)列中填NULL。

學(xué)生姓名來源于students表漫贞,科目名稱來源于subjects甸箱,分?jǐn)?shù)來源于scores表
當(dāng)查詢結(jié)果來源于多張表時(shí),需要使用連接查詢

當(dāng)查詢結(jié)果來源于多張表時(shí)迅脐,需要使用連接查詢
關(guān)鍵:找到表間的關(guān)系芍殖,當(dāng)前的關(guān)系是
students表的id---scores表的stuid
subjects表的id---scores表的subid

select students.sname,subjects.stitle,scores.score
from scores
inner join students on scores.stuid=students.id
inner join subjects on scores.subid=subjects.id;
  • 連接查詢分類如下:
  • 表A inner join 表B:表A與表B匹配的行會(huì)出現(xiàn)在結(jié)果中
  • 表A left join 表B:表A與表B匹配的行會(huì)出現(xiàn)在結(jié)果中,外加表A中獨(dú)有的數(shù)據(jù)谴蔑,未對應(yīng)的數(shù)據(jù)使用null填充
  • 表A right join 表B:表A與表B匹配的行會(huì)出現(xiàn)在結(jié)果中围小,外加表B中獨(dú)有的數(shù)據(jù),未對應(yīng)的數(shù)據(jù)使用null填充
  • 在查詢或條件中推薦使用“表名.列名”的語法
  • 如果多個(gè)表中列名不重復(fù)可以省略“表名.”部分
  • 如果表的名稱太長树碱,可以在表名后面使用' as 簡寫名'或' 簡寫名'肯适,為表起個(gè)臨時(shí)的簡寫名稱

用一個(gè)部門表,員工表演示一下內(nèi)外連接查詢

-- 部門表成榜,員工表
drop table if exists emp;
drop table if exists dept;
create table dept(
     id int auto_increment primary key,
     dname varchar(20)
);
create table emp(
     id int auto_increment primary key,
     ename varchar(20),
     did int not null,
     mgr int, 
     foreign key(did) references dept(id),
     foreign key(mgr) references emp(id)
);
insert into dept(dname) values('研發(fā)部');
insert into dept(dname) values('人事部');
insert into dept(dname) values('財(cái)務(wù)部');

insert into emp(ename,did,mgr) values('老王',1,null);
insert into emp(ename,did,mgr) values('老張',1,1);
insert into emp(ename,did,mgr) values('老趙',1,1);
insert into emp(ename,did,mgr) values('小紅',2,3);
insert into emp(ename,did,mgr) values('小麗',2,3);

/*查詢員工額編號框舔,姓名,上級的姓名*/
-- 1
select t1.id,t1.ename,t2.ename
from emp t1,emp t2
where t1.mgr = t2.id;
-- 2inner join
select t1.id,t1.ename,t2.ename
from emp t1
inner join emp t2
on t1.mgr = t2.id;
-- 3左外連接
select t1.id,t1.ename,t2.ename
from emp t1
left join emp t2
on t1.mgr = t2.id;
-- 4右外連接
select t1.id,t1.ename,t2.ename
from emp t1
right join emp t2
on t1.mgr = t2.id;
Paste_Image.png

Paste_Image.png

自關(guān)聯(lián)

概述:指用表的別名實(shí)現(xiàn)表自身的連接赎婚。

在員工表中mgr列中代表了他們的上級

/*查詢員工額編號刘绣,姓名,上級的姓名*/
select 員工表.id,員工表.ename 員工,上級表.ename 上級 from emp 員工表,emp 上級表
where 員工表.mgr = 上級表.id;
Paste_Image.png

子查詢

查詢支持嵌套使用
查詢各學(xué)生的語文挣输、數(shù)學(xué)纬凤、英語的成績

-- 查詢各學(xué)生的語文、數(shù)學(xué)撩嚼、英語的成績
select sname,
    (select sco.score from scores sco inner join subjects sub on sco.subid=sub.id 
            where sub.stitle='語文' and stuid=stu.id) as 語文,
    (select sco.score from  scores sco inner join subjects sub on sco.subid=sub.id 
            where sub.stitle='數(shù)學(xué)' and stuid=stu.id) as 數(shù)學(xué),
    (select sco.score from  scores sco inner join subjects sub on sco.subid=sub.id 
            where sub.stitle='英語' and stuid=stu.id) as 英語
from students stu;
查詢結(jié)果

內(nèi)置函數(shù)

字符串函數(shù)

-- 查看字符的ascii碼值ascii(str)停士,str是空串時(shí)返回0
select ascii('a');
-- 查看ascii碼值對應(yīng)的字符char(數(shù)字)
select char(97);
-- 拼接字符串concat(str1,str2...)
select concat(12,34,'ab');
-- 包含字符個(gè)數(shù)length(str)
select length('abc');
-- 截取字符串
-- left(str,len)返回字符串str的左端len個(gè)字符
-- right(str,len)返回字符串str的右端len個(gè)字符
-- substring(str,pos,len)返回字符串str的位置pos起len個(gè)字符
select substring('abc123',2,3);
-- 去除空格
-- ltrim(str)返回刪除了左空格的字符串str
-- rtrim(str)返回刪除了右空格的字符串str
-- trim([方向 remstr from str)返回從某側(cè)刪除remstr后的字符串str挖帘,
--   方向詞包括both、leading恋技、trailing拇舀,表示兩側(cè)、左蜻底、右
select trim('  bar   ');
select trim(leading 'x' FROM 'xxxbarxxx');
select trim(both 'x' FROM 'xxxbarxxx');
select trim(trailing 'x' FROM 'xxxbarxxx');
-- 返回由n個(gè)空格字符組成的一個(gè)字符串space(n)
select space(10);
-- 替換字符串replace(str,from_str,to_str)
select replace('abc123','123','def');
-- 大小寫轉(zhuǎn)換骄崩,函數(shù)如下
-- lower(str)
-- upper(str)
select lower('aBcD');

數(shù)學(xué)函數(shù)


-- 求絕對值abs(n)
select abs(-32);
-- 求m除以n的余數(shù)mod(m,n),同運(yùn)算符%
select mod(10,3);
select 10%3;
-- 地板floor(n)薄辅,表示不大于n的最大整數(shù)
select floor(2.3);
-- 天花板ceiling(n)要拂,表示不小于n的最大整數(shù)
select ceiling(2.3);
-- 求四舍五入值round(n,d),n表示原數(shù)站楚,d表示小數(shù)位置脱惰,默認(rèn)為0
select round(1.6);
-- 求x的y次冪pow(x,y)
select pow(2,3);
-- 獲取圓周率PI()
select PI();
-- 隨機(jī)數(shù)rand(),值為0-1.0的浮點(diǎn)數(shù)
select rand();
-- 還有其它很多三角函數(shù)源请,使用時(shí)可以查詢文檔

日期時(shí)間函數(shù)

獲取子值枪芒,語法如下
year(date)返回date的年份(范圍在1000到9999)
month(date)返回date中的月份數(shù)值
day(date)返回date中的日期數(shù)值
hour(time)返回time的小時(shí)數(shù)(范圍是0到23)
minute(time)返回time的分鐘數(shù)(范圍是0到59)
second(time)返回time的秒數(shù)(范圍是0到59)

select year('2016-12-21');
日期計(jì)算彻况,使用+-運(yùn)算符谁尸,數(shù)字后面的關(guān)鍵字為year、month纽甘、day良蛮、hour、minute悍赢、second
select '2016-12-21'+interval 1 day;

獲取年%Y决瞳,返回4位的整數(shù)
獲取年%y,返回2位的整數(shù)
獲取月%m左权,值為1-12的整數(shù)
獲取日%d皮胡,返回整數(shù)
獲取時(shí)%H,值為0-23的整數(shù)
獲取時(shí)%h赏迟,值為1-12的整數(shù)
獲取分%i屡贺,值為0-59的整數(shù)
獲取秒%s,值為0-59的整數(shù)

/*日期-->字符串*/
select date_format('2017-10-20','%Y年%m月%d日')
/*字符串-->日期*/
select str_to_date('2017年10月20日','%Y年%m月%d日')

當(dāng)前日期current_date()
select current_date();
當(dāng)前時(shí)間current_time()
select current_time();
當(dāng)前日期時(shí)間now()
select now();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锌杀,一起剝皮案震驚了整個(gè)濱河市甩栈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌糕再,老刑警劉巖量没,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異突想,居然都是意外死亡殴蹄,警方通過查閱死者的電腦和手機(jī)究抓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來饶套,“玉大人漩蟆,你說我怎么就攤上這事〖寺” “怎么了怠李?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蛤克。 經(jīng)常有香客問我捺癞,道長,這世上最難降的妖魔是什么构挤? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任髓介,我火速辦了婚禮,結(jié)果婚禮上筋现,老公的妹妹穿的比我還像新娘唐础。我一直安慰自己,他們只是感情好矾飞,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布一膨。 她就那樣靜靜地躺著,像睡著了一般洒沦。 火紅的嫁衣襯著肌膚如雪豹绪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天申眼,我揣著相機(jī)與錄音瞒津,去河邊找鬼。 笑死括尸,一個(gè)胖子當(dāng)著我的面吹牛巷蚪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播濒翻,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼屁柏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了肴焊?” 一聲冷哼從身側(cè)響起前联,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎娶眷,沒想到半個(gè)月后似嗤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡届宠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年烁落,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了乘粒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,626評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡伤塌,死狀恐怖灯萍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情每聪,我是刑警寧澤旦棉,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站药薯,受9級特大地震影響绑洛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜童本,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一真屯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧穷娱,春花似錦绑蔫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至梯刚,卻和暖如春凉馆,著一層夾襖步出監(jiān)牢的瞬間薪寓,已是汗流浹背亡资。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留向叉,地道東北人锥腻。 一個(gè)月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像母谎,于是被迫代替她去往敵國和親瘦黑。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 前言 我們使用SQL查詢不能只使用很簡單奇唤、最基礎(chǔ)的SELECT語句查詢幸斥。如果想從多個(gè)表查詢比較復(fù)雜的信息,就會(huì)使用...
    暖熊熊閱讀 609評論 0 0
  • 認(rèn)真算一算 社保的繳費(fèi)周期咬扇、費(fèi)率甲葬、以及最后能領(lǐng)取多少?社毙负兀可不可以你想什么時(shí)候領(lǐng)養(yǎng)老金都可以经窖? 能不能保證領(lǐng)多少坡垫?...
    美格發(fā)型工作室閱讀 137評論 0 0
  • 在火車上大半夜醒來然后就睡不著了,想著你現(xiàn)在應(yīng)該已經(jīng)熟睡了画侣,不知道你昨晚什么時(shí)候回去的冰悠,都沒發(fā)條消息過來,有點(diǎn)難過...
    風(fēng)花微涼閱讀 202評論 0 0
  • 財(cái)富=價(jià)值*杠桿 最近老大跑到上海配乱、深圳溉卓,去找導(dǎo)師,去建人脈搬泥,老大說他學(xué)到了很多東西的诵,大腦都被更新成光滑的了,他說...
    堅(jiān)果姐姐閱讀 351評論 3 1