業務系統中經常需要統計不同期間的業務資料,以銷售收入統計為例,業務主管可能需要在一張**中同時顯示截止到某乙個日期(往往就是當前日期)的當日合計、月度合計、季度合計、年度累計,如下表:
統計日期
產品當日收入
月度收入
季度收入
年度收入
2019-5-25
產品001
1002000
30000
400000
2019-5-25
產品002
2002100
28000
350000
如果使用程式語言,統計不同時間段的合計,在邏輯上很簡單,只是工作量和程式效能問題。如果想在乙個查詢語句中同時輸出這些不同時間段的合計數,就沒那麼簡單了。
下面以乙個虛擬的【業務收入】表為例,介紹這個統計查詢的實現思路。該錶的結構如下圖:
因為是帶條件的查詢,所以首先需要定義乙個【統計日期】的變數,並賦值,比如:
declare @d date
set @d='2019-5-25' -- 或者 set @d=getdate() 設定當期系統日期為統計截止日期
然後,分別查詢當日合計、月度合計、季度合計、年度合計。
當日合計的sql如下:
select 日期,產品
,sum(收入) 當日收入
from 業務收入
where 1=1
and 日期 = @d
group by 日期,產品
月度合計的sql很類似,只是在where條件中有區別:
select @d 日期,產品 -- 此處將 @d 輸出為【日期】字段,是為了顯示統計日期
,sum(收入) 月度收入
from 業務收入
where 1=1
and 日期 <= @d
and 日期 >= convert(datetime,convert(char(8),@d, 120)+'1') -- 這是取月初1號的日期
group by 產品
季度合計與此類似,只是起始日期條件有變化:
select @d 日期,產品
,sum(收入) 季度收入
from 業務收入
where 1=1
and 日期 <= @d
and 日期 >= dateadd(quarter, datediff(quarter,0, @d),0) -- 這是取季度首日的日期
group by 產品
同樣的,年度合計是從年初1月1日開始,至統計截止日期:
select @d 日期,產品
,sum(收入) 年度收入
from 業務收入
where 1=1
and 日期 <= @d
and 日期 >= convert(datetime,convert(char(4),@d, 120)+'-1-1') -- 這是取年初1月1日的日期
group by 產品
直接執行上面的這些sql語句,得到的查詢結果將是4個分離的結果集,如下圖:
為了合併這4個結果集,首先將每個資料集都新增幾個null欄位,然後使用union all將它們合併起來。
比如,對於當日收入,新增3個null欄位,分別是月度收入、季度收入、年度收入,sql語句變成:
select 日期,產品
,sum(收入) 當日收入
,null 月度收入 -- 新增null欄位
,null 季度收入 -- 新增null欄位
,null 年度收入 -- 新增null欄位
from 業務收入
where 1=1
and 日期 = @d
group by 日期,產品
其他3個sql語句採用類似方法,使得4個sql語句都輸出4個統計週期的合計收入,如下圖:
使用union all將4個sql語句合併,然後再按日期、產品進行彙總,最終的sql語句如下:
declare @d date
set @d='2019-5-25'
select 日期,產品
,sum(當日收入) 當日收入
,sum(月度收入) 月度收入
,sum(季度收入) 季度收入
,sum(年度收入) 年度收入
from
(select
日期,產品
,sum(收入) 當日收入
,null 月度收入
,null 季度收入
,null 年度收入
from 業務收入
where 1=1
and 日期 = @d
group by 日期,產品
union all
select
@d 日期,產品
,null 當日收入
,sum(收入) 月度收入
,null 季度收入
,null 年度收入
from 業務收入
where 1=1
and 日期 <= @d
and 日期 >= convert(datetime,convert(char(8),@d, 120)+'1')
group by 產品
union all
select
@d 日期,產品
,null 當日收入
,null 月度收入
,sum(收入) 季度收入
,null 年度收入
from 業務收入
where 1=1
and 日期 <= @d
and 日期 >= dateadd(quarter, datediff(quarter,0, @d),0)
group by 產品
union all
select
@d 日期,產品
,null 當日收入
,null 月度收入
,null 季度收入
,sum(收入) 年度收入
from 業務收入
where 1=1
and 日期 <= @d
and 日期 >= convert(datetime,convert(char(4),@d, 120)+'-1-1')
group by 產品
) vgroup by
日期,產品
執行這個sql語句,最終結果如下:
這個結果,正是期待的結果集形式。
月季流水賬
最近比較忙,好久沒有博了,先花幾天把我部落格周圍的荒草拔掉先.然後嘮叨嘮叨最近兩個月來印象比較深的值得一記的東西和想法。0.先詳細地談談工作 3 damn f u c k why程式除錯not通過?此處省去5千萬字 總之,這是有成效的乙個月,成功的乙個月,勝利的乙個月,在 的指引下,我們的工作取得了...
月季流水賬
最近比較忙,好久沒有博了,先花幾天把我部落格周圍的荒草拔掉先.然後嘮叨嘮叨最近兩個月來印象比較深的值得一記的東西和想法。0.先詳細地談談工作 3 damn f u c k why程式除錯not通過?此處省去5千萬字 總之,這是有成效的乙個月,成功的乙個月,勝利的乙個月,在 的指引下,我們的工作取得了...
C 自然周,月,季度計算。
判斷時間是否和伺服器時間是一天 public static bool judgetimeistoday datetime cs 計算當前季度多少天 public static intdatediff 計算當前月有多少天 public static intgetmonthdays 計算本週的周一日期 ...