? ? 標準結構化查詢語言(Structured Query Language)簡稱SQL,sql是我們日常工作中使用最多一項技能,寫sql可以說是一個可以干到退休的技能。看似簡單,但要精通卻很難。 熟悉我的小伙伴都知道我之前寫過關于《sql實踐》的文章,小伙伴們說它是經典,后來經過我與小伙伴交流,發現來自基層的小伙伴技術水平普遍不高,在處理一個問題時候,經常會岀現“卡殼“現象。市面關于這種HIT真正實用技術干貨,實在很難尋覓!實在有必要重寫一遍,全面提升大家sql能力。sql包括增、刪、改、查,創建表、刪除表、修改表等等內容,我們今天所講的sql是一種狹義上select語句,這個使用最頻繁,也是最復雜的。寫一篇關于技術類的文章,既要深刻,又要通俗易懂,的確要耗費我不少精力,如果大家覺得此文對你或者有需要的人有所幫助,歡迎您轉發!
一、sql會不會淘汰?
? ? 大家滿懷熱情點進來學習一下sql,首先要搞清楚一個問題,sql會淘汰嗎?要回答這個問題,首先有必要了解sql發展背景,它是關系型數據庫誕生的產物,有時候不得不佩服這些先輩,當關系型數據庫起步發展的時候,就制定了一個統一的操作標準,就是SQL標準,所有關系型數據庫(mysql/mssql/oracle)都會實現這個標準,這也是為什么sql會常勝不衰的原因,所以sql會不會淘汰,要看關系型數據庫會不會淘汰?到目前為止沒有看到任何關系型數據庫淘汰的跡象,傳統關系型數據庫過渡到分布式關系型數據庫,這是未來極有可能發生的事。
? ? ? 你可能會問市面不是有一個nosql的東西?首先nosql翻譯成中文,不是”沒有sql“的意思,而是”不僅僅有sql,還有其它“,nosql是not only sql的簡稱。nosql說的一種補充,什么意思,sql主要處理結構化的數據,nosql主要處理非結構化的數據。目前來說nosql沒有一個統一的標準,都是按照用途來發展,比如鍵值(Key-Value)存儲數據庫, Redis;列存儲數據庫,Cassandra;文檔型數據庫, MongoDb;圖形(Graph)數據庫,Neo4J。
二、什么是IT高手
? ? ? 扎實理論基礎知識,這是決定一個人水平飛得有多高。靈活運用這個基礎知識(非常難),才決定一個人水平有多牛。為什么我會說經常出現”卡殼“現象,有些看上去很難的問題,其實運用一些基礎知識就可以解決,但是要做這一點非常困難。
? ? 我們通常對高手定義都是可以處理日常工作中一些難題,注意我說的是一些難題,不要期望解決所有的難題,什么是日常工作的難題?特點一:問題偶然出現,無法重現問題;特點二,沒有明顯的邏輯錯誤,沒有解決問題思路;特點三:問題本身就很難(比如數據結構與算法)。比如,我們HIS里面醫技系統就有這樣一個難題一直無法解決,護士錄入A代碼記錄,后臺偶然間會保存B代碼記錄,半年時間偶然出現1,2次,但是我們在HIS程序里面各種極端操作測試,始終無法重現問題,實在令人不解!
? 在這里我分享一下曾經處理過難題,你會驚訝的發現,解決問題的方法很簡單,都是用的最基本的基礎知識解決的,但是你想到這種解決方法,非常不易!
第一個問題:使用netbeans開發環境,在書寫js函數queryStr的時候,按ctrl+shift+F格式化代碼的時候,偶然會出現結構混亂,有時候發現導航器js未出現這個函數,如下圖所示:
問題原因:? 原來js代碼與html在同一個文件來寫的,原來在queryStr函數是包含動態生成html代碼的片斷,雖然這個代碼放變量賦值里面,在格式化的時候,netbeans依然會檢測這個html是否合法,導致縮進混亂,和導航器分析不出這個函數。我個人猜測格式化的底層實現,將整個文檔解析,解析html標簽,即便html標簽寫在js字符串變量里面,如果沒有完整配對,依然會出問題。
解決方法:保證queryStr涉及的html字符完整,并且里面提及的函數必須聲明出來。
第二個問題:下面來分享mysql bug。通過mysqldump導出來sql腳本,測試還原過程中,出現[Err] 1064錯誤,跟蹤到是以下語句出錯,百思不得其解,當時寫進數據庫沒有任何問題,為什么導出來,再導進去的時候就報錯。
[Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''
質控科劉成章要求統計2018.04.01---2018-06-30門診醫生的收' at line 9
可能存在的原因:
? UPDATE `info`.`fh_comm_detail` set `cl_proc` = ‘.....’? WHERE (`mxid` = '100005')
cl_proc后面的值當中包含/*,*/注釋符號,mysql去解析的時候,觸發bug,原本包含在‘’中字符串含義發生變化,導致語句報錯。(但是我在mysql查詢分析器,怎么樣都模擬不出來這種錯誤,就是偶然發生)。
解決方法:將/*注釋符號替換為其他字符即可,比如”--”,讓其不觸發解析注釋串。
問題三:聯網醫保金額與本地程序計算,有少數患者偶爾會存在金額不一致問題。翻看程序代碼左看右看,都沒有問題,如下所示。
lc_jine_sum = round(tab_1.tabpage_1.dw_1.getitemnumber(1,"jine_total"),2)
問題原因:我突然想起一個基礎知識,計算機浮點數本身是不準確的,每次運算都有可能得出不同的結果,既然不準確,為什么我們還會大規模使用計算機來解決問題,解決方法就是提高計算機處理精度,讓它無限逼近準確。什么意思,我們大部分現實當中,大部分都是計算到2位小數,最多也是4位小數,但是計算機就無所謂,10-20位都可以處理,10-20位小數精度再截取2-4位小數,當然就可以做到準確無誤。大家是否遇到過這種問題,明明只有一位小數,把這些數字加起來的時候,你會看到一長串小數,這就是計算機內部使用高精度計算的問題,如下圖所示。
? ? 計算機內部使用高精度的小數(一般是10幾位以上),來解決小數不準確的問題。所以我當時就把代碼改了一下,果然改完以后,問題從此沒有出現過。這就是利用基礎知識去解決實際當中的難題,你看得我寫的很簡單,其實想到這個方法是非常困難的。
lc_jine_sum =round(tab_1.tabpage_1.dw_1.getitemnumber(1,"jine_total"),4) //先取出 4 位小數
lc_jine_sum = round(lc_jine_sum,2) //再進行 2 位小數四舍五入
三、解決一個sql問題基本思路
? ? 日常工作sql語句主要用途,臨時統計數據、后臺查數找問題原因、制作報表。拿到一個sql語句的問題首先我們先從業務角度分析,后臺是否存在數據,它們是否存在相應關聯?沒有數據,沒有關聯,后繼工作亳無意義。
? ? 舉例說明,患者用藥追蹤,統計患者用了哪個廠家哪個批次的藥品。統計的意義,如果發藥哪個批次有問題,可以精準找到相關患者。第一個問題,后臺有數據嗎,有的。his里面基本上都有藥品出入庫、患者用藥數據,但是藥品管理的廠家、批次,與患者用藥之間沒有關聯。這也是his系統里面的一個難題,目前我還沒有看到靠譜的解決方案。由上述可以得知,患者用藥追蹤,這個問題無法用sql解決。
? ? 其次,通常你拿到一個稍微復雜sql問題一般不能一步到位寫出來。別操之過急,學會化解問題。舉例說明,統計歷史連續某段時間內每日在院人數,假設his系統中沒有生成數據(每天將在院人數數據拷貝生成一個中間表數據)。
? ? 第一步分解:假設你現在統計歷史某日(2020-03-01)的在院人數,在院人數 = (入院日期 <= 在院人數 <= 出院日期) + 一直未出院的在院人數。
? 第二步分解:模擬生成連續某段時間,比如2020-03月份,再關聯生成每日在院人數
? ? 最后,需要驗證統計出來的數據是否正確,經過驗證,統計出來的歷史在院數據是完全正確的,發現有個別出現1,2個人的誤差,是因為人為修改了”入院日期“,”出院日期“所致,如果你想檢驗sql水平怎么樣,我給你一個判斷標準,是否使用了中間表。嚴格來說,只要數據庫存在數據,存在關聯,就可以用sql語句查出來,如果你精通sql是不會用到中間表的。