IT咨詢顧問:group by與join引發的項目救火
我又一次進行了項目救火,這次的原因是group by與join胡亂的堆徹導致的整個業務系統審核流程發生嚴重的錯誤。基礎的sql表關聯,group by,子表都理不清,我也只能對你面帶微笑,不想對你解析原因,你就按照我提供給你的模板改你全部的業務sql層(XML文件的sql)吧。
很簡單的一對多表關聯
用戶表,customerId代表用戶的唯一id,insertTime代表這條數據何時存入的。與之對應的是表單表,外鍵customerId表明這個保單是哪個客戶的,同時unit表明出該保單的機構,insertTime也是插入時間。
業務背景
前端列表顯示出每一天投保的客戶信息(客戶連續兩天投保,則顯示兩條該客戶數據,如上面intsmaze客戶),點擊每條記錄的詳情可以查看該客戶當天的保單詳情。
審核權限劃分:一個客戶一天投保的多個保單可能會來自多個出單機構,比如上面intsmaze,06-21的三個保單出自上海,北京,深圳,那麽怎麽劃分,借助group by的"隨緣法則",intsmaze 06-21號就取數據插入順序最前的上海,特朗普 06-21 就取杭州。
他們的原產sql
SELECT * from customer c LEFT JOIN insurance i on c.customerId=i.customerId and c.insertTime=i.insertTime where c.flow=‘0‘ GROUP BY c.customerId
查詢的結果是兩條數據,很顯然少了一條intsmaze 06-22號的
雖然有問題,但是感覺很難爆出給用戶的,它是怎麽出現的了?
這要說審核流程了,默認數據進來是初審,用戶表的flow是0。
當用戶審核intsmaze的這一條數據後,數據變得如下
我們可以看到flow=‘0‘初審,intsmaze的unit由上海變成了北京,那是因為這條問題sql隱藏的數據終於出現了。
此時flow=‘1‘復審的數據如下
然後有趣的事情來了,審核人員此時又將初審的intsmaze 北京 提交到復審,這個時候復審應該有兩條數據,但是他到復審那裏還是就看到一條數據。然後就出大事了,最後我就馬革裹屍過來救火了。
解決方案
join的時候是幾個字段,group by就幾個字段,加上insertTime即可
SELECT * from customer c LEFT JOIN insurance i on c.customerId=i.customerId and c.insertTime=i.insertTime GROUP BY c.customerId,c.insertTime
unit判斷,導致同一條數據兩個機構均可審核
他的unit的判斷放在join後的where條件上
SELECT * from customer c LEFT JOIN insurance i on c.customerId=i.customerId and c.insertTime=i.insertTime where c.flow=‘1‘ and i.unit=‘北京‘ GROUP BY c.customerId
這導致一個有趣的問題就是,比如intsmaze 06-21 這個客戶,它分別能被北京,上海,深圳三個機構看到,其他機構是看不到。然後就出現一個有趣的現象:"誰動了我的數據,我明明沒有審核,為什麽到復審了,北京復審頁面看到這條數據初審提交人事上海,這是怎麽一回事嘛?"。
這個問題我只顯示結果,不想解釋,最後附上解決方案。
SELECT * from customer c LEFT JOIN insurance i on c.customerId=i.customerId and c.insertTime=i.insertTime where c.flow=‘1‘ GROUP BY c.customerId
這個客戶本來是該上海機構去審核
可是我發現,如果北京機構人登錄,也是可以看到這條記錄進行審核
SELECT * from customer c LEFT JOIN insurance i on c.customerId=i.customerId and c.insertTime=i.insertTime where c.flow=‘1‘ and i.unit=‘北京‘ GROUP BY c.customerId
如何解決,子表唄
SELECT * from ( SELECT c.customerId,c.insertTime,unit,money from customer c LEFT JOIN insurance i on c.customerId=i.customerId and c.insertTime=i.insertTime where c.flow=‘1‘ GROUP BY c.customerId )temp where temp.unit=‘北京‘
最終我提供的sql模板如下:
SELECT * from ( SELECT c.customerId,c.insertTime,unit,money from customer c LEFT JOIN insurance i on c.customerId=i.customerId and c.insertTime=i.insertTime where c.flow=‘1‘ GROUP BY c.customerId,c.insertTime )temp where temp.unit=‘北京‘
模板提供後,剩下的事情當然不是我去改了,畢竟我已經吐了幾口血了。我只負責找出問題,提供解決方案,然後功能顧問就全方位的改自己的sql。我則一旁陪伴直至改完後,系統沒有出現他們無法解決的毛病後就離場修身養性咯。
ps:救了幾次火後,我曉得當初為什麽我被面試,別人問我你開發中遇到什麽奇怪的bug沒,我當時真的沒有啊,我確實沒有遇到什麽奇怪的bug,因為你如果真的按照語法規則開發,其實很多問題都是不會出現的。之所以會出現,往往是基礎太薄弱,然後也不理解上來就模仿,然後就會出錯。
IT咨詢顧問:group by與join引發的項目救火