一個sql和C#程式碼結合的分組求和的查詢
業務描述: 業務主表(tab_main 主鍵 id), 供應商名稱(supplier), 金額(amount 需要統計求和),還有分類( 有單獨的表categoryid),集中採購標記欄位(tenderMark),稽核時間(auditTime)
分類表: (tab_category ),分類id: categoryid,分類名稱:categoryname
主表是明細資料, 要對這個明細 進行統計, 固定列: 供應商名稱,總金額,集採金額, 後面是各個分類的列,有多少個分類,就有多少列(動態的)
現在寫這個sql 思路:
(1) 基礎查詢sourceData
with sourceData as (
selecta.supplier, a.amount, (case whena.tenderMark=1 thena.amount else 0 end) astenderAmount,a.categoryid
where a.auditTime between to_date('2022-01-01 00:00:00',yyyy-mm-dd hi24:mi:ss) andto_date('2022-03-01 00:00:00',yyyy-mm-dd hi24:mi:ss)
)
(2)根據分類 構造 資料集dataALL
with dataALL as (
select 1 as Category0, 0 as Category1, 0 as Category2, 0 as Category3,T.* fromsourceData T wherecategoryid=1
union allselect 0 as Category0, 1 as Category1, 0 as Category2, 0 as Category3,T.*fromsourceDataT wherecategoryid=2
union all select 0 as Category0, 0 as Category1, 1 as Category2, 0 as Category3,T.* fromsourceDataT wherecategoryid=3
union all select 0 as Category0, 0 as Category1, 0 as Category2, 1 as Category3,T.*fromsourceDataT wherecategoryid=3
... --動態的, 有多少個分類 就 重複拼接,通過C#程式碼實現, 構建對應的列資料
)
(4)根據分類,group by
select supplier,sum(amount) asamountSum, sum(tenderAmount) astenderAmountSum
,(case when Category0=1 then sum(amount) else 0 end) asCategory0AmountSum
,(case when Category1=1 then sum(amount) else 0 end) asCategory1AmountSum
,(case when Category2=1 then sum(amount) else 0 end) asCategory2AmountSum
,(case when Category3=1 then sum(amount) else 0 end) asCategory3AmountSum
... --動態拼接
from dataALL group bysupplier,Category0,Category1,Category2,Category3
(5) 之前以為上面就寫完了,後來發現 部署到正式上, 一個供應商對應多條資料出來,
原來當 一個 供應商 有多個分類的時候,資料就會....
那就繼續group by 合併一下
selectsupplier, sum(amountSum)amountSum, sum(tenderAmountSum)tenderAmountSum
,sum(Category0AmountSum)Category0AmountSum
,sum(Category1AmountSum)Category1AmountSum
,sum(Category2AmountSum)Category2AmountSum
,sum(Category3AmountSum)Category3AmountSum
... --動態拼接
from (上面的(4)的查詢 ) newTab
group bysupplier
order bysupplier asc
測試一下資料, 沒問題了,就可以部署了.
上面標記顏色的部分, 是可以用 C#程式碼 進行 迴圈填充的, 多定義幾個 StringBuilder 迴圈 拼接字串.
小結一下: 將複雜的問題 簡單化, 分類為 3個的時候怎麼寫, 4個的時候 怎麼寫,然後推斷成 動態的怎麼拼接 sql.
PS: (1) 我知道有其他的實現方式, 或者什麼 行轉列的 寫法 ,但是好在 我知道我這個業務的分類 不會很多(一般4到6個,不會超過7個)
就這樣簡單寫一下,效率也還行,湊合用,實現效果就行.
(2) 先把資料取出來,然後用C# 程式碼 分組合並, 也是一個思路 ,但是這個 有悖於 開發規範.
一般 資料能在資料庫 裡面操作的, 直接資料庫 裡面操作,資料庫不方便操作的, 拿出來用 C# 程式碼補充操作.
我給這個寫法批2個字: 拙技