4

我承认这是迄今为止我必须面对的最复杂的 SQL 语句之一。我在这个问题上有点碰壁,我希望有人能帮帮我。

我在数据库中有这张表

 Item      ActiveTime(sec)      DateTime
 -------------------------------------------
 1         10                   2013-06-03 17:34:22   -> Monday
 2         5                    2013-06-04 17:34:22   -> Tuesday
 1         2                    2013-06-03 12:34:22   -> Monday
 1         3                    2013-06-04 17:33:22   -> Tuesday

我希望它在我的 SQL 语句之后看起来像这样

 Item     Mon     Tues    Wed    Thurs   Fri  Sat   Sun    Average
 -----------------------------------------------------------------------------------
 1        6       3                                        5
 2                5                                        5

这个怎么运作

对于第 1 项:

您可以看到星期一的平均值是 6,因为 (10 + 2) / 2 天,星期二的平均值只有 3,因为它在星期二只发生一次。第 1 项的平均值为 5,因为 (10 + 2 + 3)/3 = 5

对于第 2 项:

它在星期二只发生一次,因此第 2 项星期二的平均值是 5。平均值是 5,因为它只发生一次,所以 5/1 = 5。

到目前为止,我提出了以下 SQL 语句,旨在显示按工作日细分的每个项目的平均 ActiveTime 以及每个项目的总体平均 ActiveTime:

Select *,((ISNULL([Sunday],0) +ISNULL([Monday],0)+ ISNULL([Tuesday],0)+ 
         ISNULL([Wednesday],0)+ ISNULL([Thursday],0)+ISNULL([Friday],0)+
         ISNULL([Saturday],0)) / 
         ( CASE WHEN [Sunday] is null  
           THEN 0 ELSE 1 END +
           CASE WHEN [Monday] is null 
           THEN 0 ELSE 1 END + 
           CASE WHEN [Tuesday] is null 
           THEN 0 ELSE 1 END + 
           CASE WHEN [Wednesday] is null 
           THEN 0 ELSE 1 END + 
           CASE  WHEN [Thursday] is null 
           THEN 0 ELSE 1 END +   
           CASE WHEN [Friday] is null 
           THEN 0 ELSE 1 END +  
           CASE WHEN [Saturday] is null 
           THEN 0 ELSE 1 END )) as Avg 
        FROM ( SELECT * FROM 
             ( 
             SELECT a.ResetTime as ResetTime,a.ApartmentDescription as  Apartment,
             DATENAME(WEEKDAY,a.DateTime) _WEEKDAY 
             FROM tblECEventLog a 
             ) 
             AS v1 PIVOT (AVG(ResetTime) FOR _WEEKDAY IN  
                ([Sunday],[Monday],[Tuesday],[Wednesday],[Thursday],[Friday], [Saturday]) 
             )
             AS v2 
             )
             AS v3

运行上述 SQL 将产生以下结果:

 Item     Mon     Tues    Wed    Thurs   Fri  Sat   Sun    Average
 -----------------------------------------------------------------------------------
 1        6       3                                        4.5
 2                5                                        5

所以它几乎可以工作,但请注意值 4.5,它是通过 (6+3)/2 得到的,这是不正确的,我不想只添加平均值。Andybody 可以建议对我的 SQL 语句进行改进,以使用每个项目的实际平均 ActiveTime 计算平均值?

4

2 回答 2

6

您应该可以使用avg() over()来获得结果。这将允许您按以下方式对数据进行分区item

avg(ActiveTime) over(partition by item) Avg_Item

所以完整的查询将是:

SELECT item,
  [Sunday],
  [Monday],
  [Tuesday],
  [Wednesday],
  [Thursday],
  [Friday],
  [Saturday],
  Avg_Item
FROM 
( 
  SELECT a.ActiveTime as ActiveTime,a.Item as  Item,DATENAME(WEEKDAY,a.DateTime) _WEEKDAY,
    avg(ActiveTime) over(partition by item) Avg_Item
  FROM TableA a  
) AS v1 PIVOT 
(
  AVG(ActiveTime) 
  FOR _WEEKDAY IN 
(
  [Sunday],[Monday],[Tuesday],[Wednesday],[Thursday],[Friday],[Saturday])
) AS v2;

查看SQL 演示

于 2013-06-06T17:43:39.823 回答
2

您可以使用group by而不是pivot

select  Item
,       avg(case when datename(weekday, DateTime) = 'Sunday' then ActiveTime end) d1
,       avg(case when datename(weekday, DateTime) = 'Monday' then ActiveTime end) d2
,       avg(case when datename(weekday, DateTime) = 'Tuesday' then ActiveTime end) d3
,       avg(case when datename(weekday, DateTime) = 'Wednesday' then ActiveTime end) d4
,       avg(case when datename(weekday, DateTime) = 'Thursday' then ActiveTime end) d5
,       avg(case when datename(weekday, DateTime) = 'Friday' then ActiveTime end) d6
,       avg(case when datename(weekday, DateTime) = 'Saturday' then ActiveTime end) d7
,       avg(ActiveTime) AllDays
from    TableA
group by
        Item

SQL Fiddle 的示例。

于 2013-06-06T17:55:20.827 回答