连续多列的T-SQL AVG

时间:2018-04-08 00:18:25

标签: sql-server tsql pivot average

我试图从AdventureWorks数据库中选择每个区域的人均销售额。

由于这是聚合一行中的多个列而不是列中的多个行,所以我似乎需要一个子查询,临时表,也许是一个CTE,但我不知道如何确定要采取的方向或如何编写它。

期望的结果:

| SalesTerritory | SalesPeople | 2011   | 2012    | 2013    | 2014    | AvgSales
+----------------+-------------+--------+---------+---------+---------+----------
| Australia      | 1           | NULL   | NULL    | 184105  | 1237705 | [avg]
| Canada         | 2           | 115360 | 3426082 | 2568323 | etc...  | [avg]

代码:

SELECT
    pvt.SalesTerritory,
    COUNT(pvt.SalesPersonID) AS SalesPeople,
    SUM(pvt.[2011]),
    SUM(pvt.[2012]),
    SUM(pvt.[2013]),
    SUM(pvt.[2014])

    --What's the best way to AVG the sales by year by sales person for each territory here?
 FROM    
     (SELECT
          st.[Name] AS [SalesTerritory],
          soh.[SalesPersonID],
          soh.[SubTotal],
          YEAR(DATEADD(m, 6, soh.[OrderDate])) AS [FiscalYear]
      FROM   
          [Sales].[SalesPerson] sp
      INNER JOIN  
          [Sales].[SalesOrderHeader] soh ON sp.[BusinessEntityID] = soh.[SalesPersonID]
      INNER JOIN  
          [Sales].[SalesTerritory] st ON sp.[TerritoryID] = st.[TerritoryID]
      INNER JOIN  
          [HumanResources].[Employee] e ON soh.[SalesPersonID] = e.[BusinessEntityID]
      INNER JOIN  
          [Person].[Person] p ON p.[BusinessEntityID] = sp.[BusinessEntityID]) AS soh
      PIVOT
          (SUM([SubTotal]) FOR [FiscalYear] IN ([2011], [2012], [2013], [2014])) AS pvt
GROUP BY    
    pvt.SalesTerritory

2 个答案:

答案 0 :(得分:0)

您有几种选择:

1)使用cross apply。查询看起来像:

select
    *
from
    (
        --put your query here
    ) t
    cross apply (select AvgSales = avg(v) from (values ([2011]), ([2012]), ([2013]), ([2014])) q(v)) q

2)自己计算平均值

SELECT
    pvt.SalesTerritory,
    COUNT(pvt.SalesPersonID) AS SalesPeople,
    SUM(pvt.[2011]),
    SUM(pvt.[2012]),
    SUM(pvt.[2013]),
    SUM(pvt.[2014]), 

    ISNULL(SUM(pvt.[2011]), 0) + ISNULL(SUM(pvt.[2012]), 0) 
    + ISNULL(SUM(pvt.[2013]), 0) + ISNULL(SUM(pvt.[2014]), 0)
    / CASE WHEN SUM(pvt.[2011]) > 0 THEN 1 ELSE 0 END
    + CASE WHEN SUM(pvt.[2012]) > 0 THEN 1 ELSE 0 END
    + CASE WHEN SUM(pvt.[2013]) > 0 THEN 1 ELSE 0 END
    + CASE WHEN SUM(pvt.[2014]) > 0 THEN 1 ELSE 0 END
FROM    
     ...
GROUP BY    
    pvt.SalesTerritory

答案 1 :(得分:0)

据我了解您的问题,您需要每个地区的年销售额每位销售员的平均值。 Uzi的答案为每个地区提供了所有销售人员的年销售额的平均值。您可以将该结果除以销售人员的数量,或使用如下查询:

SELECT pvt.SalesTerritory, COUNT(pvt.SalesPersonID) AS SalesPeople, 
       SUM(pvt.[2011]) AS [2011], SUM(pvt.[2012]) AS [2012],
       SUM(pvt.[2013]) AS [2013], SUM(pvt.[2014]) AS [2014],
       AVG(pvt.AvgSubTotal) AS AvgSubTotal
FROM (
  SELECT y.SalesTerritory, y.SalesPersonID, y.FiscalYear, y.SubTotal, 
         AVG(y.SubTotal) OVER (PARTITION BY y.SalesTerritory) AS AvgSubTotal
  FROM (
    SELECT x.SalesTerritory, x.SalesPersonID, x.FiscalYear, SUM(x.SubTotal) AS SubTotal
    FROM (
      SELECT st.Name AS SalesTerritory, soh.SalesPersonID, soh.SubTotal, 
             YEAR(DATEADD(m, 6, soh.OrderDate)) AS FiscalYear
      FROM Sales.SalesPerson sp
      INNER JOIN Sales.SalesOrderHeader soh ON sp.BusinessEntityID = soh.SalesPersonID
      INNER JOIN Sales.SalesTerritory st ON sp.TerritoryID = st.TerritoryID
      INNER JOIN HumanResources.Employee e ON soh.SalesPersonID = e.BusinessEntityID
      INNER JOIN Person.Person p ON p.BusinessEntityID = sp.BusinessEntityID
    ) x
    GROUP BY x.SalesTerritory, x.SalesPersonID, x.FiscalYear
  ) y
) AS soh
PIVOT (SUM(SubTotal) FOR FiscalYear IN ([2011], [2012], [2013], [2014])) AS pvt
GROUP BY pvt.SalesTerritory;

Northwest区域的结果不同,但我不确定您想要的结果。