1. 程式人生 > >IT咨詢顧問:group by與join引發的項目救火

IT咨詢顧問:group by與join引發的項目救火

一對多 模仿 insert 取數據 spa com png color 我們

我又一次進行了項目救火,這次的原因是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引發的項目救火