【psql】array元素聚合運算解決辦法
psql提供了數組類型array,但是沒有直接對array中元素求和/求均值/中位數等統計運算的方法。對於用習慣了python中簡單的np.sum()的我來講,簡直是非常不方便了。儘管有將array中的元素挨個提取出來相加的笨辦法,但是如果不同行的array中元素個數不一樣,這一方式就不是很友好了。
這幾天剛好工作中碰到了這個問題,百度大法完全不管用,可能不同行array元素長度不一樣本來就是不太規範的做法,但是畢竟表結構是不受自己控制的,因此在大牛同事的幫助下想出了這樣一個辦法:
簡單來講就是兩個步驟:
比如現在salary表裏有一行數據是這樣的: 某個銷售員工叫張三基本工資10000,每完成一單,提成2%,這個月他一共做了四單,提成分別是2000,300,20,780;但是因爲公司內控需要或者數據庫格式設計的缺陷,他的每筆工資數據都被合併記在一行,最後是這樣一條:
name | salarys |
---|---|
張三 | 10000+2000+300+20+780 |
這裏的salarys還是string格式
現在問題來了,這樣的員工有幾千個,財務月底要結算每個人這個月的總工資,該怎麼求和?
- 將string轉成array:string_to_array(string,sep)
其中,string是要轉換的字符串,sep是分隔符
比如有一個string是“a,b,c”,指定分隔符爲逗號,就可以把它轉成{a, b, c}的array
顯然,在我們的問題裏,分隔符是加號‘+’,sql如下:
select name, string_to_array(salarys, ‘+’) salarys from salary
得到的結果就會是:
name | salarys |
---|---|
張三 | {10000, 2000, 300, 20, 780} |
- 將array列拆成多行:unnest(array)
unnest這個函數可以把一個array裏的每一個元素單獨放到一行,其他列直接複製,此時sql變爲:
select name, unnest(string_to_array(salarys, ‘+’)) salarys from salary
得到的結果就會是:
name | salarys |
---|---|
張三 | 10000 |
張三 | 2000 |
張三 | 300 |
張三 | 20 |
張三 | 780 |
- 用group by彙總聚合:
看到上一步的結果以後,我想只要有sql基礎的人都知道該怎麼處理了,用name作爲key進行groupby即可,這裏的例子裏我們要做的是求和所以用sum,如果需求不是求和而是其他類型的聚合,只要在這一步裏把sum函數換成其他聚合函數即可。
所以最後的sql是:
**
select name, sum(salarys) from
(select name, unnest(string_to_array(salarys, ‘+’)) salarys from salary) a
group by name**
得到的結果:
name | salarys |
---|---|
張三 | 13100 |