如何成爲寫SQL高手(下)

四、SQL基礎理論知識

    掌握基礎理論知識是成爲SQL高手第一步,我不會照搬教科書式的講課,我只會講解我認爲你最應該的掌握的3個知識點。

  1、集合(Set)。我給大家一個簡單的概念,sql裏面一切皆集合。SQL 以關係代數爲基礎發展出來的一門語言,關係代數主要是“集合”。

sql語句形式:select .... from ....

集合在sql當中的表現形式:每一個select語句都是一個集合,寫在from後面的每個表、子查詢、視圖可以算作一個集合。

第一種情況

第二種情況

第三種情況

2、笛卡爾積

    select * from table1,table2,table1存在a列m行,table12存在b列n行,最後形成的集合是(a+b)列,(m*n)行記錄。我們學計算機你會發現一個現象,越往前追溯,都會一個簡單模型,如果你把所有sql問題往前推,最後都會看到 “笛卡爾積”的身影。

  我舉一個簡單的例子,SQL理論中會把選取字段這個操作叫作“投影(project) ”。我不知道大家有無想過這個問題,爲什麼叫“投影"這個概念,而不是叫其他名稱,因爲任何sql語句其實到最後都是迴歸一個“笛卡爾積”,你在選取字段操作,好似對“笛卡爾積”做了一次“投影"。

3、集合之間的關係

    集合之間的關係 一對一、一對多(最頻繁)、多對多(幾乎不用),在數據庫表中通常用FOREIGN KEY表示一對多的關係 。爲什麼要關注它們之間的關係,主要寫sql的語句發現記錄重複現象,你一定要檢查是不是一對多,多對多之間的關係。但是當sql語句複雜以後了,即便你分析清楚集合之間的關係,很可能出現記錄重複的現象,當與你的預期不符,我們可以distinct去重。

五、SQL中實戰技巧

      這次我不再分析如何去書寫一個sql語句,我相信大家多多少少會寫sql。我只是跟大家分享一下我掌握的技巧。

  1、能少寫,就不要多寫(write less,do more)。爲什麼要這樣,第一個提高效率;第二個減少出錯機率。舉例說明:假設我們寫內連接語句。其實是有2種寫法,我推薦大家使用第一種寫法。

特別注意在oracle數據庫當中,左連接、右連接有一種簡寫的方式。

  2、爲什麼有時候別名需要增加雙引號。當你的別名,包含特殊符號的時候,就要增加雙引號,比如+、-、*、/、(、)。

3、使用null注意事項。null指的是理論意義上的絕對的空,不指任何含義。所以空字串、空數組、空對象表示含義的空,不是null。所以null一般使用身份運算符 is,以示區分,is null或者is not null。像python是用is判斷,但是java,js中用==來判斷,有些編程語言對這個問題並沒有嚴格區分。

4、union 和union all之間的區別。union將兩個集合去掉重複記錄合併在一起,union all只是簡單合併在一起。

5、group by使用問題。有時候會發現聚合函數,感覺數值明顯錯誤,先去掉group by 查看原始記錄,看where條件是否寫錯。

6、充分利用數據庫提供函數,簡化sql書寫難度。舉例說明:同時統計採購物品A、B、C、D分類的小計

同時統計某個科室的出庫給中心藥房的基數、節約的小計。

    當然我不可能窮舉所有的技巧,我只是把我使用最多一些技巧分享給大家,精通sql需要大家長期實踐。

六、案例分析

    我曾經收到來自基層醫療機構的多位小夥伴的求助,他們在寫sql的時候出現“卡殼”問題。其實不管使用oracle、mssql、mysql解決問題的原理思路都是一樣,只不過表現形式不同。以下分享協助小夥伴處理問題2個案例。

    案例一:某小夥伴遇到數據上報問題,某個藥品入庫與出庫數據需要在同一行展示,因爲“入庫與出庫”來源於不同的表,小夥伴用了一種最原始的方法來處理。小夥伴的解決方案,把“入庫數據”統計出來放入一箇中間表,把“出庫數據”統計出來放入一箇中間表,再將兩個中間表關聯查詢。

入庫

出庫

    小夥伴感覺這樣處理比較麻煩,期望能用一條sql語句解決問題。我幫小夥伴分析是否可以用一條sql搞定的可能性,第一,對於來自於不同來源數據“入庫”和“出庫”,相當於不同的集合,可以使用union連起來;第二,union合併有個特點,要求兩個集合是相同字段類型,相同的字段的個數,缺少的字段可以使用虛擬列來解決;第三,將union結果當作子查詢(相當於得到一個新的集合),再進行group by處理,可以完成整個操作。 最終sql語句部份截圖如下所示:

入庫補充虛擬列

出庫補充虛擬列

union當作子查詢再進行group by

案例二:某小夥伴,製作檢驗視圖給第三方調用,當某個檢驗結果,超過了正常範圍,顯示↑,↓,否則爲空,如下圖所示。

需求

使用case when

  小夥伴在百度搜尋很多資料或許也是看了我的文章,想到了可以用case when來解決這個問題,但是執行過程中報“sql server 從數據類型varchar 轉換爲 float時出錯”。

出錯信息

  因爲我對mssql不熟悉這個問題對於我來說還是有一點的難度。我的思考過程如下,既然是數據類型出錯,ISNUMERIC(b.lac13) > 0,這個條件嫌疑就很大,isnumeric沒有真正把“數字值”過濾乾淨,我百度一下isnumeric返回值,只有兩個返回值1,0。我當時敏銳感覺到問題就在這裏,ISNUMERIC(b.lac13) > 0這種寫法本身就是一個“坑”,假設判斷ISNUMERIC(‘陰性’) 返回0,0>0就成立,convert去轉換的時候就會報“sql server 從數據類型varchar 轉換爲 float時出錯”。

  我叫小夥伴改成ISNUMERIC(b.lac13)  and CONVERT(float, b.LAC10) < CONVERT(float, b.lac13),再測試,果然問題就解決了。1代表true,0代表false這個習慣是從C語言那裏繼承過來的。不過小夥伴有點擔心,如果ISNUMERIC(‘陰性’)  and CONVERT(float, ‘陰性’) 這樣判斷不是一樣有問題嗎?我瞭解小夥伴這個擔心,如果他掌握一個基礎知識,這種擔心是完全是多餘的。什麼意思,一般編程語言都會有一個if條件熔斷機制。舉例說明:條件1 and 條件2 and 條件3,假設條件1是false,就可以決定整個表達式的值,意味着條件2 , 條件3不會再去做判斷處理,就好像發生了“熔斷”。再比如:條件1 or 條件2 or 條件3,假設條件1是true,就可以決定整個表達式的值,意味着條件2 , 條件3不會再去做判斷處理。

  如果小夥伴還是不放心,可以將條件改成ISNUMERIC(b.lac13) == 1,就不會存在理解不了這個問題了。

處理效果

七、總結

    俗說“光說不練假把式”。多寫sql才能掌握真技術,同時也要不停的跳出自己的“舒適區”。爲什麼有人幹了10年,水平還是很菜,因爲他只不過把有些事情重複幹了10年而己,並沒有真的成長。每次寫sql的時候,能不能不用中間表、能不能再簡單一點,每次挑戰一下自己,完成同樣的效果。所謂的高手,大部分都在挑戰自己能力邊界。最後祝大家都從文中有所收穫,成爲sql高手!


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章