上个月的每周平均值(每天)

时间:2013-08-22 16:53:57

标签: sql sql-server tsql aggregate-functions

你好再次好叠人。 我面临着上个月每周平均每周平均值(例如,Monday_Avg,Tuesday_Avg ......等)的困境 我已成功使用以下代码获取上个月的月平均值。但是,我不太了解sql中的日期/时间函数如何完成此任务。

这适合我获得月平均值。

ALTER procedure [dbo].[usp_consumation]
@strMonth varchar(2),
@strYear varchar(4),
@strPrevMonth varchar(2),
@strPrevYear varchar(4)
as
--set @strMonth = '05'
--set @strYear = '2013'
--set @strPrevMonth = '04'
--set @strPrevYear = '2013'

declare @tbl_PrevMonthAverage table(cell varchar(25),average_d numeric(18,4))
drop table ##tempCIUnits
drop table ##tempCIUnitsTotal

declare @FieldName varchar(150)
declare @FieldAbv varchar(50)
declare @strSql varchar(8000)
declare @strFields varchar(5000)
declare @strFieldsSum varchar(5000)
declare @intCounter integer
\

--Get avarage past month
set @strFields = ' '
set @intCounter = 0
declare curStrSQLUnits cursor for 
            select name, right(name,4) name_abv  
            from sys.columns 
            where system_type_id = 108
            and object_id = isnull((select top 1 id from sites.dbo.sysobjects where name = 'tbl_Revenue_'+@strPrevYear+@strPrevMonth),0)
            and name like 'count_d_%'
            order by name asc
open curStrSQLUnits
fetch next from curStrSQLUnits into @FieldName,@FieldAbv
while @@fetch_status = 0
begin 
      set @intCounter = @intCounter + 1   
      set @strFields = @strFields + @FieldName + '+'
      fetch next from curStrSQLUnits into  @FieldName,@FieldAbv
end
close curStrSQLUnits
deallocate curStrSQLUnits
set @strFields = left(@strFields,len(@strFields)-1)
set @strSql = 'select [Cell], (' + @strFields + ')/'+CONVERT(varchar,@intCounter)+' as avg_previous_month '
set @strSql = @strSql + ' from sites.dbo.tbl_Revenue_'+@strPrevYear+@strPrevMonth + ' order by Cell asc'
insert into @tbl_PrevMonthAverage(cell,average_d) exec (@strSql)

解决问题的另一种方法。

USE [Sites]
GO

declare @strPrevMonth varchar(2)
declare @strPrevYear varchar(4)

set @strPrevMonth = '07'
set @strPrevYear = '2013'

declare @FieldName varchar(150)
declare @FieldAbv varchar(50)
declare @strSql varchar(8000)
declare @strFieldsSum varchar(5000)

declare @intCounter integer
declare @strFields varchar(5000)
declare @intCounter_1 integer
declare @strFields_1 varchar(5000)
declare @intCounter_2 integer
declare @strFields_2 varchar(5000)
declare @intCounter_3 integer
declare @strFields_3 varchar(5000)
declare @intCounter_4 integer
declare @strFields_4 varchar(5000)
declare @intCounter_5 integer
declare @strFields_5 varchar(5000)
declare @intCounter_6 integer
declare @strFields_6 varchar(5000)
declare @intCounter_7 integer
declare @strFields_7 varchar(5000)

--Get avarage past month
set @strFields = ' '
set @intCounter = 0
set @strFields_1 = ' '
set @intCounter_1 = 0
set @strFields_2 = ' '
set @intCounter_2 = 0
set @strFields_3 = ' '
set @intCounter_3 = 0
set @strFields_4 = ' '
set @intCounter_4 = 0
set @strFields_5 = ' '
set @intCounter_5 = 0
set @strFields_6 = ' '
set @intCounter_6 = 0
set @strFields_7 = ' '
set @intCounter_7 = 0

declare curStrSQLUnits cursor for 
            select name, right(name,4) name_abv  
            from sys.columns 
            where system_type_id = 108
            and object_id = isnull((select top 1 id from sites.dbo.sysobjects where name = 'tbl_CellId_Revenue_'+@strPrevYear+@strPrevMonth),0)
            and name like 'minutes_d_%'
            order by name asc
open curStrSQLUnits

fetch next from curStrSQLUnits into @FieldName,@FieldAbv

while @@FETCH_STATUS = 0
begin 

      set @intCounter = @intCounter + 1   
      set @strFields = @strFields + @FieldName + '+'

        if (datepart(weekday,@strPrevMonth+'/'+RIGHT(@FieldName,2)+'/'+@strPrevYear)) = 1
        begin
            set @intCounter_1 = @intCounter_1 + 1   
            set @strFields_1 = @strFields_1 + @FieldName + '+'    
        end

        if (datepart(weekday,@strPrevMonth+'/'+RIGHT(@FieldName,2)+'/'+@strPrevYear)) = 2
        begin
            set @intCounter_2 = @intCounter_2 + 1   
            set @strFields_2 = @strFields_2 + @FieldName + '+'    
        end

        if (datepart(weekday,@strPrevMonth+'/'+RIGHT(@FieldName,2)+'/'+@strPrevYear)) = 3
        begin
            set @intCounter_3 = @intCounter_3 + 1   
            set @strFields_3 = @strFields_3 + @FieldName + '+'    
        end

        if (datepart(weekday,@strPrevMonth+'/'+RIGHT(@FieldName,2)+'/'+@strPrevYear)) = 4
        begin
            set @intCounter_4 = @intCounter_4 + 1   
            set @strFields_4 = @strFields_4 + @FieldName + '+'    
        end

        if (datepart(weekday,@strPrevMonth+'/'+RIGHT(@FieldName,2)+'/'+@strPrevYear)) = 5
        begin
            set @intCounter_5 = @intCounter_5 + 1   
            set @strFields_5 = @strFields_5 + @FieldName + '+'    
        end

        if (datepart(weekday,@strPrevMonth+'/'+RIGHT(@FieldName,2)+'/'+@strPrevYear)) = 6
        begin
            set @intCounter_6 = @intCounter_6 + 1   
            set @strFields_6 = @strFields_6 + @FieldName + '+'    
        end

        if (datepart(weekday,@strPrevMonth+'/'+RIGHT(@FieldName,2)+'/'+@strPrevYear)) = 7
        begin
            set @intCounter_7 = @intCounter_7 + 1   
            set @strFields_7 = @strFields_7 + @FieldName + '+'    
        end

      fetch next from curStrSQLUnits into @FieldName,@FieldAbv

end
close curStrSQLUnits
deallocate curStrSQLUnits
set @strFields = left(@strFields,len(@strFields)-1)
set @strFields_1 = left(@strFields_1,len(@strFields_1)-1)
set @strFields_2 = left(@strFields_2,len(@strFields_2)-1)
set @strFields_3 = left(@strFields_3,len(@strFields_3)-1)
set @strFields_4 = left(@strFields_4,len(@strFields_4)-1)
set @strFields_5 = left(@strFields_5,len(@strFields_5)-1)
set @strFields_6 = left(@strFields_6,len(@strFields_6)-1)
set @strFields_7 = left(@strFields_7,len(@strFields_7)-1)


set @strSql = 'select isnull((' + @strFields_1 + '),0)/'+CONVERT(varchar,@intCounter_1)+' as Sun_Avg_PrevMnth '
set @strSql = @strSql + ', isnull((' + @strFields_2 + '),0)/'+CONVERT(varchar,@intCounter_2)+' as Mon_Avg_PrevMnth ' 
set @strSql = @strSql + ', isnull((' + @strFields_3 + '),0)/'+CONVERT(varchar,@intCounter_3)+' as Tue_Avg_PrevMnth '
set @strSql = @strSql + ', isnull((' + @strFields_4 + '),0)/'+CONVERT(varchar,@intCounter_4)+' as Wed_Avg_PrevMnth '
set @strSql = @strSql + ', isnull((' + @strFields_5 + '),0)/'+CONVERT(varchar,@intCounter_5)+' as Thu_Avg_PrevMnth '
set @strSql = @strSql + ', isnull((' + @strFields_6 + '),0)/'+CONVERT(varchar,@intCounter_6)+' as Fri_Avg_PrevMnth '
set @strSql = @strSql + ', isnull((' + @strFields_7 + '),0)/'+CONVERT(varchar,@intCounter_7)+' as Sat_Avg_PrevMnth '
set @strSql = @strSql + ' from sites.dbo.tbl_Revenue_'+@strPrevYear+@strPrevMonth + ' order by CellId asc'
exec (@strSql)

1 个答案:

答案 0 :(得分:1)

我将通过一个非常简单的示例来回答我认为你的意思“每周平均值(每天)”,然后让你弄清楚你需要如何将它整合到这个大规模的存储过程中,各种各样的代码似乎与您尝试解决的实际问题无关。我可以继续讨论你是如何错误地使用全局临时表或质疑为什么需要表变量或怀疑名为tbl_Revenue_201307的表的完整性,但同样,他们似乎没有任何东西处理你遇到的问题:

  

获取上个月的每周平均值(例如,Monday_Avg,Tuesday_Avg ...等)...   
我对sql中的日期/时间函数知之甚少   完成这项任务。

假设您有一个包含四列的表格,一个datetime和三个decimal(18,2)

CREATE TABLE dbo.tbl_Revenue_201307
(
  d DATETIME,
  val1 DECIMAL(18,2),
  val2 DECIMAL(18,2),
  val3 DECIMAL(18,2)
);

一些示例数据:

INSERT dbo.tbl_Revenue_201307 VALUES
('20130701',12,15,18),('20130701',13,14,15),('20130702',5,1,5), 
('20130703',12,15,18),('20130703',13,9,13),('20130703',5,1,5),  
('20130704',12,15,18),('20130704',13,1,12),('20130705',5,1,5),  
('20130705',12,15,18),('20130706',13,11,16),('20130714',5,1,5);

您想查看该月的所有数据,并将其平均值显示为“它”(“它”表示val1 + val2 + val3的总和每个工作日。因此,一个值代表当月所有星期日的平均值,一个值代表所有星期一的平均值,等等总共7个单独值。两个可以执行此操作的查询(取决于您是否需要行或列中的数据):

SELECT
  wd = DATEPART(WEEKDAY, date_col),
  dn = LEFT(DATENAME(WEEKDAY, date_col), 3) + '_Avg', 
  [avg] = AVG(val1 + val2 + val3)
FROM dbo.tbl_Revenue_201307
GROUP BY DATENAME(WEEKDAY, date_col), DATEPART(WEEKDAY, date_col)
ORDER BY wd;

SELECT * FROM 
(
  SELECT 
    col = LEFT(DATENAME(WEEKDAY, date_col),3) + '_Avg',
    val = AVG(val1 + val2 + val3)
  FROM dbo.tbl_Revenue_201307
  GROUP BY LEFT(DATENAME(WEEKDAY, date_col),3)
) AS p
PIVOT (MAX(val) FOR col IN 
  ([Sun_Avg],[Mon_Avg],[Tue_Avg],[Wed_Avg],[Thu_Avg],[Fri_Avg],[Sat_Avg])) AS d;

结果:

wd   dn        avg
--   -------   ---------
1    Sun_Avg   11.000000
2    Mon_Avg   43.500000
3    Tue_Avg   11.000000
4    Wed_Avg   30.333333
5    Thu_Avg   35.500000
6    Fri_Avg   28.000000
7    Sat_Avg   40.000000

Sun_Avg     Mon_Avg     Tue_Avg     Wed_Avg     Thu_Avg     Fri_Avg     Sat_Avg
---------   ---------   ---------   ---------   ---------   ---------   ---------
11.000000   43.500000   11.000000   30.333333   35.500000   28.000000   40.000000