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