0

你好再次好堆栈的人。我面临着获取上个月每天的每周平均值(例如,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)
4

1 回答 1

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的“it”(“it”表示++的总和val2)。因此,一个值表示该月所有星期日的平均值,一个值表示所有星期一的平均值,等等,总共有 7 个单独的值。可以做到这一点的两个查询(取决于您是否想要行或列中的数据):val3

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
于 2013-08-22T17:59:33.127 回答