因為做的是類似saas的系統,關於同乙個業務沒會有不同的視角,有管理員,有類別分類的,有特別邏輯處理的。總而言之涉及到很多方面,再加上歷史遺留問題導致導致的資料問題,這sql寫起來真的酸爽。
除了簡單的關聯,還要考慮到乙個效率問題,最近就因為case when導致了乙個線上查詢緩慢,差一點就要超過客戶端設定的超時請求設定的乙個問題。
問題詳情:
現在有乙個檢查盤點資產的要求,之前只是要求在資料庫有拿過資產的員工去發檢查清單,
檢查單表 check
檢查詳情(針對涉及到的資產每乙個生成對應資料)check_detail
貨物資產 asset 員工表employee
員工返回檢查結果(針對的涉及到的員工每乙個生成資料) employee_check
問題來了之前的邏輯,實際上員工領用資產了那他的check_detail和employee_check是對應的上的
但是沒有的話就對應不上了,之前只檢查有資產的員工,現在還要檢查沒有領用資產的(萬一有驚喜呢)
mybaitis寫的sql一部分
and case when aio.no_use_asset_employee_join = 1 then ( aius.employee_id = # )
else ( aiod.employee_id = # && aius.employee_id = # ) end
就是有1的時候所用人都參與,0的時候要滿足兩個條件,在範圍的員工還要有資產
但是一上生產就完了,一張表只有幾萬條資料巨卡,兩三秒才返回差一點就超時的那種
檢查sql 用explain分析發現該走的索引也都走了,就是很慢,而且隨便從日誌找一條sql發現實際涉及到的行數也不多,大概是三個解析,最多的也才兩百多行,為什麼會這麼慢?
實際上就是結果集else的時候他既要匹配aiod.employee_id = # 又要 aius.employee_id = #
類似於sql函式,沒走索引,效率很慢。
那優化怎樣,就是盡量都走優化,既然都用到這個aiod.employee_id = # ,就把他提出來,然後改造成這個樣 ,1=1永遠為true就是不再做篩選
and aius.employee_id = #
and case when aio.no_use_asset_employee_join = 1 then ( 1 = 1)
else ( aiod.employee_id = # ) end
思考:
就是不要把太多條件去放進case when裡面,這樣會導致不走索引,只能單純去比較就會很慢。盡量拆分出公共部分,盡可能去走索引查詢。
關於SQL的case when魅力
最近去面試碰到了兩道關於資料庫的筆試題目 1 有member表 m id int,m varchar 20 其中m 有三個不同值 男 女 null 要求用一條sql語句把member表的m 字段更新成m 的值 男 變成 女 女 變成 男 null 不變 答 update member set m c...
ORACLE關於case when語句
其中,最好玩和最有用的是oracle裡面的case when then else end語句,剛開始學的時候還是懵懂懵懂的,不是很懂,後來老師給了很多關於oracle的作業,做著做著慢慢就懂了很多,下面我來講幾個例子。1 題目 統計列印各科成績,各分數段人數 課程id,課程名稱,100 85 85 ...
hql 中的case when運用查詢
有以下hql string hql select new com.ks.admin.report.dto.reportmonthwithdrawaldto count sum ct.tradetotal sum case when ct.tradetotal 0 then 1 else 0 end ...