Mysql中關(guān)于on,in,as,where的區(qū)別
Mysql on,in,as,where的區(qū)別
答:Where查詢條件,on內(nèi)外連接時候用,as作為別名,in查詢某值是否在某條件里
創(chuàng)建2個表:student,score
student:
score:
where
SELECT * FROM student WHERE s_sex='男'
例如:on
SELECT * FROM student LEFT JOIN score?on student.s_id=score.s_id;
on和where組合:
SELECT * FROM student LEFT JOIN score on student.s_id=score.s_id WHERE s_name='趙雷'?
例如:in
SELECT * FROM score WHERE s_id in (SELECT s_id FROM student WHERE s_name='趙雷')
as
select * from score as a LEFT JOIN student as b on a.s_id=b.s_id where s_name='趙雷'
Mysql語句問題解決
1、left join數(shù)據(jù)篩選問題
on后面的條件只能對left join右邊的表進行篩選,左表匹配不到右表數(shù)據(jù)會在原右表位置處顯示null,left join左邊的表數(shù)據(jù)不受約束,將on后的條件加到where后會對所有數(shù)據(jù)進行篩選。
2、相同數(shù)據(jù)重復(fù)篩選使用問題
with <name> as()
mysql內(nèi)可以使用with as生成臨時表,<name>為臨時表的名字,使用如下:
with arc as(? ? ? select id,arc.title,update_time,is_top,cId,pid,name_id from article arc where is_del = 0? )? select * from arc
with...as的作用范圍只有一次sql執(zhí)行的時間,執(zhí)行過后就不再存在,根據(jù)例子我們本要處理article表,但表里的數(shù)據(jù)并非都是我們需要的,所系先篩選建立了一個臨時表arc,我們會對arc進行操作。
如果只是上述例子的簡單操作是沒必要使用with...as的,但是當(dāng)我們需要將article表與其他表進行聯(lián)查甚至嵌套時,會出現(xiàn)要多次進行is_del = 0的判斷,最終出來的sql語句可能個十分復(fù)雜,并且極易出錯,但使用arc就不需要在對數(shù)據(jù)進行重復(fù)篩選了。
with...as里的sql可以更復(fù)雜些,比如article表里有name_id,但更多時候我們希望使用name,我們可以預(yù)先在with...as內(nèi)查找好,再使用臨時表去做其他操作。
3、根據(jù)某個字段排序取每個類別最后三條數(shù)據(jù)或前三條數(shù)據(jù)
這算是個比較經(jīng)典的一個問題了,我初學(xué),只會一種解題方法,但會盡力講的簡單通俗點。
示例:
select * from (? select cId,title,content(? ? ? select count(*)+1 from arc a1 where (a1.cId = a2.cId) and a1.updateTime > a2.updateTime? )updateTimeSort from arc a2? ) a3? where updateTimeSort <= 3 order by cId,updateTime desc
示例中cId是類別id,updateTime 是更新時間,解決問題是選取arc內(nèi)每個類別最晚更新的的三條數(shù)據(jù),就像新聞的首頁需要為每個分類選出最新的三條新聞,按照數(shù)據(jù)庫里的數(shù)據(jù)我們可以使用排序 order by cId,updateTime desc 對數(shù)據(jù)按類別和更新時間進行排序,但去取每個類別的特定幾條數(shù)據(jù),現(xiàn)有數(shù)據(jù)庫是做不到的,因此我們可以添加一個臨時字段。
updateTimeSort 它表示的是每個類別中每個子項在這個類別中的排序,在當(dāng)前問題中這個臨時字段應(yīng)該是和字段 updateTime 相關(guān)的,根據(jù)更新時間為類別中的每個子項排出順序。
如示例代碼,我們能找到a1和a2這兩個表,他們都是arc表的別稱,通過子查詢的形式結(jié)合在一起,以a2為主,去a1表內(nèi)查找類別和a2當(dāng)前數(shù)據(jù)相同的,并且更新時間晚于a2當(dāng)前數(shù)據(jù)的數(shù)據(jù)數(shù)量,能看到 count(*)+1 也就是數(shù)量加一了,不加一也可以,只是當(dāng)一條數(shù)據(jù)在它所處類別更新時間最晚時count(*) 的值是0,若果使用count(*)+1 我們就可以將數(shù)據(jù)從1開始排序。
最終我們只要選取 updateTimeSort <= 3 的數(shù)據(jù)即可,如果想要篩選最早發(fā)布的新聞也只需要將updateTimeSort 的篩選邏輯變更一下即可,在示例代碼中即將
a1.updateTime > a2.updateTime 更改為 a1.updateTime < a2.updateTime
可以看到示例代碼中還有一個表a3,它其實時一個臨時表,前面我們了解了with..as可以生成臨時表,也重這次代碼中可以看出,臨時表也可以以另一種形式存在,with...as我們只有當(dāng)sql復(fù)雜時才會使用,一般來說現(xiàn)在這種方式能幫我們解決不少問題了,各有優(yōu)劣,看情況使用。
4、業(yè)務(wù)邏輯書寫位置問題
接觸sql多了會發(fā)現(xiàn),sql其實能幫我們解決一定的業(yè)務(wù)問題,明顯的有sql的存儲過程和方法,對sql語句的批量處理其實在一定程度上幫我們解決一定的業(yè)務(wù)問題,但缺點也很明顯,當(dāng)新手接觸這個項目時他很難搞清楚某個功能到底是如何實現(xiàn)的,不利于維護。
一般來說我們解決業(yè)務(wù)是在server層,有時會使用sql解決一些問題,但很少,在sever處理受制于計算機硬件,在數(shù)據(jù)庫處理受制于數(shù)據(jù)庫性能,相比之下,計算機硬件更易于擴展,因此還是不推薦大量使用sql解決問題的。
例如上個問題:根據(jù)某個字段排序取每個類別最后三條數(shù)據(jù)或前三條數(shù)據(jù)問題,雖然問題基本解決但讓存在一些 ‘bug’,例如排序時會產(chǎn)生1、2、3、3、4這種排序,這是因為同個類別內(nèi)有兩條數(shù)據(jù)更新時間重復(fù)了,那我們直觀想法(還是要看個人經(jīng)驗值)應(yīng)該是,既然問題出在數(shù)據(jù)庫,那應(yīng)該在數(shù)據(jù)庫查詢的時候就解決這個問題,但事實上,讓數(shù)據(jù)庫去解決并不好解決,數(shù)據(jù)庫的強項在于各種搜索算法,不在于邏輯處理,因此我們就要轉(zhuǎn)移到server層處理,會有不少人陷于這個坑,花費大量時間去找辦法讓數(shù)據(jù)庫去處理這類問題,但其實就算數(shù)據(jù)庫處理得了,它也不一定有server層處理的效率高,當(dāng)然如果是為了學(xué)習(xí)更多東西,這些時間也是值得花的,但是這種解題思路還是要改變下的。將1、2、3、3、4問題交給server處理也就是利用java等高級語言處理這種問題,相信熟用這些語言的開發(fā)者解決這些問題都是小case了。
5、查找另一表內(nèi)和本表相關(guān)字段的數(shù)量
先復(fù)習(xí)下知識:用過count函數(shù)的人都清楚一旦使用count這類聚合函數(shù),不做其他處理數(shù)據(jù)就會歸為一行數(shù)據(jù),但很多時候我們并不期望這樣的結(jié)果,以此就要想些辦法能用聚合函數(shù),也能獲取很多數(shù)據(jù),我常用的是利用group by分組。
回歸問題,現(xiàn)有(現(xiàn)不討論表是否合理)文章表(id,title,content)有文章id,標(biāo)題,文章內(nèi)容三個字段,點贊收藏表(id,arc_id,fav,like)有表id,文章id,收藏字段(0未收藏,1收藏),點贊字段(0未點贊,1點贊),現(xiàn)要查詢文章表內(nèi)每篇文章的點贊收藏數(shù),sql語句:
select art.title,art.content,? count(case afl.fav when 1 then 1 end) as collectNum,? count(case afl.like when 1 then 1 end) as likeNum? from article art? left join article_favor_like afl on afl.arc_id = art.id? group by afl.arc_id //這是關(guān)鍵
如果沒有g(shù)roup by afl.arc_id 后果就是,查出來一行數(shù)據(jù),數(shù)據(jù)還牛頭不對馬嘴,但通過對文章收藏表中的文章id進行分組就可以針對每個文章id查詢數(shù)據(jù),這樣left join時右表就有每個文章id對相應(yīng)的收藏數(shù)與點贊數(shù),而不是表內(nèi)所有點贊數(shù)和收藏數(shù),最終數(shù)據(jù)也是我們所需的。
6、關(guān)于union的使用
例子:
select id,title,content,1 isArc from arc? union? select id,name,content,0 isArc from news
- 使用union進行的是上下整合
- 被聯(lián)合的數(shù)據(jù)列數(shù)要求一致
- 列數(shù)相同,數(shù)據(jù)類型不同會自動進行數(shù)據(jù)類型轉(zhuǎn)換
- 聯(lián)合后的列的名字由聯(lián)合中第一次出現(xiàn)的列名為依據(jù),即使后續(xù)被聯(lián)合數(shù)據(jù)有自己的列名也不會使用,在例子中最終列名為:id,title,content,name等列名不會使用,因此使用union一般配合別名使用統(tǒng)一結(jié)果。
- 有時候會區(qū)分?jǐn)?shù)據(jù)是哪個表的,可以通過附加額外的字段來區(qū)別,就像例子中的isArc字段,news表中的isArc可以不寫,原因也就是第4條,最終列名由第一次出現(xiàn)的列名決定,后續(xù)數(shù)據(jù)列名有沒有都可以。
7、limit的巧用
limit一般用于分頁,功能是獲取指定區(qū)間內(nèi)的數(shù)據(jù),因此我們也可以用它來減少數(shù)據(jù)庫的查詢,例子:
select * from arc where id = 12 limit 1
數(shù)據(jù)庫查詢由索引還好,沒有索引是要遍歷數(shù)據(jù)庫的,有些數(shù)據(jù)經(jīng)由條件篩選在邏輯上應(yīng)該是唯一的,使用limit 1可以使數(shù)據(jù)庫查詢到該數(shù)據(jù)時不再搜索,減少數(shù)據(jù)庫搜索次數(shù),但這種方法僅是一種技巧,想大幅度優(yōu)化sql還要另想辦法。
8、update ignore和insert ignore的使用
//標(biāo)題是唯一索引,'新標(biāo)題'存在則更新操作不執(zhí)行? update ignore arc set title = '新標(biāo)題'? ? //標(biāo)題是唯一索引,'標(biāo)題1號'存在則插入操作不執(zhí)行? insert ignore into arc values(null,'標(biāo)題1號','文章內(nèi)容')
有這種需求,數(shù)據(jù)存在時不執(zhí)行任何操作,不存在則更新或插入,一個辦法是使用ingore,它會忽略數(shù)據(jù)庫報錯,而數(shù)據(jù)庫執(zhí)行原子操作時報錯是會回滾的,因此只要我們給數(shù)據(jù)加上主鍵或唯一索引,當(dāng)被更新字段或插入字段與原有數(shù)據(jù)沖突時會報錯,但因為ingore會忽視這種報錯,后端也就不會報錯,sql也未執(zhí)行,達到了目的,有人會對報錯敏感,其實也沒什么,報錯也是在檢查數(shù)據(jù)是發(fā)現(xiàn)不合理之處給的一個提醒或警告,對數(shù)據(jù)庫無害的。
9、mysql存在更新,不存在則插入
區(qū)別于上面那個需求,這個是當(dāng)插入的數(shù)據(jù)存在時更新數(shù)據(jù),不再是不做任何操作,例子:
//本例子中title不是唯一索引,id是主鍵? insert into arc values(1,'標(biāo)題1號','文章內(nèi)容')? on duplicate key update title='標(biāo)題1號' //若要更新多個字段使用','隔開,例:title='標(biāo)題1號',content='文章內(nèi)容'
在例子中,當(dāng)id為1的數(shù)據(jù)存在時,更新標(biāo)題和內(nèi)容,不存在則插入,如果執(zhí)行更新操作,未設(shè)置新值的字段保持原來的值。
還有一個REPLACE INTO也可以達到這種效果,區(qū)別在于,REPLACE INTO更新時是先刪除后插入會破壞原有索引,id為3的數(shù)據(jù)更新時會刪除插入id為4的數(shù)據(jù),未更新新值的字段設(shè)置為默認(rèn)值或null。
無論是兩個中的哪種方式判斷數(shù)據(jù)是否存在的依據(jù)都是主鍵和唯一索引。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
mysql數(shù)據(jù)備份與恢復(fù)實現(xiàn)方法分析
這篇文章主要介紹了mysql數(shù)據(jù)備份與恢復(fù)實現(xiàn)方法,結(jié)合實例形式分析了mysql數(shù)據(jù)備份與恢復(fù)常見實現(xiàn)方法與相關(guān)操作注意事項,需要的朋友可以參考下2020-04-04MySQL中隱式轉(zhuǎn)換的踩坑記錄以及解決方法分享
這篇文章主要和大家分享一個MySQL隱式轉(zhuǎn)換時踩過的坑,差點把服務(wù)器整崩潰了,以及最后的解決辦法。文中的示例代碼講解詳細(xì),感興趣的可以了解一下2022-11-11MySQL Version確認(rèn)問題(版本確認(rèn))
這篇文章主要介紹了MySQL Version確認(rèn)問題(版本確認(rèn)),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12win10下mysql 5.7.23 winx64安裝配置方法圖文教程
這篇文章主要為大家詳細(xì)介紹了win10下mysql 5.7.23 winx64安裝配置方法圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-09-09MySql .frm數(shù)據(jù)庫文件導(dǎo)入的問題
手頭有.frm 文件,怎樣導(dǎo)入數(shù)據(jù)庫?。?/div> 2009-07-07最新評論