查找用于将财政季度结果与上一年进行比较的查询

Find the query for comparing fiscal quarter results with the previous year

使用 MS SQL Server 2014 和 AdventureWorks2012 数据库。

目前正在尝试制定正确的查询以获得一个结果,该结果显示每个销售人员在同一行的会计季度的总销售额,与上一年的会计季度进行比较。我应该在结果中包含的列是;

我的以下查询不包括最后 2 列,因为我不确定如何获取它们?然而,没有它们的查询似乎也不正确,因为它没有得到想要的结果。

我曾尝试 运行 此代码,但 GROUP BY 中没有 soh.OrderDate,这是我之前为另一个相关查询所做的事情,但是此 returns 出现以下错误因此,我将其重新包含在 GROUP BY;

Column 'Sales.SalesOrderHeader.OrderDate' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.


SELECT pp.LastName, sp.BusinessEntityID AS SalesPersonID,
    CASE
      WHEN soh.OrderDate BETWEEN '2013-07-01' AND '2014-06-30' 
        THEN '2013'
    END AS FY,
    CASE 
      WHEN MONTH(soh.OrderDate) BETWEEN 7 AND 9 THEN '1'
      WHEN MONTH(soh.OrderDate) BETWEEN 10 AND 12 THEN '2'
      WHEN MONTH(soh.OrderDate) BETWEEN 1 AND 3 THEN '3'
      WHEN MONTH(soh.OrderDate) BETWEEN 4 AND 6 THEN '4'
    END AS FQ,
    CASE 
      WHEN soh.OrderDate BETWEEN '2013-07-01' AND '2014-06-30' 
        THEN 
          SUM(CASE
        WHEN MONTH(soh.OrderDate) BETWEEN 7 AND 9 THEN soh.SubTotal
        WHEN MONTH(soh.OrderDate) BETWEEN 10 AND 12 THEN soh.SubTotal
            WHEN MONTH(soh.OrderDate) BETWEEN 1 AND 3 THEN soh.SubTotal
        WHEN MONTH(soh.OrderDate) BETWEEN 4 AND 6 THEN soh.SubTotal
          END)
    END AS FQSales, 
    CASE 
      WHEN soh.OrderDate BETWEEN '2012-07-01' AND '2013-06-30' 
        THEN 
          SUM(CASE
        WHEN MONTH(soh.OrderDate) BETWEEN 7 AND 9 THEN soh.SubTotal
        WHEN MONTH(soh.OrderDate) BETWEEN 10 AND 12 THEN soh.SubTotal
        WHEN MONTH(soh.OrderDate) BETWEEN 1 AND 3 THEN soh.SubTotal
        WHEN MONTH(soh.OrderDate) BETWEEN 4 AND 6 THEN soh.SubTotal
          END)
    END AS SalesSameLastFQ
FROM Sales.SalesPerson sp
INNER JOIN Person.Person pp 
    ON sp.BusinessEntityID = pp.BusinessEntityID
INNER JOIN Sales.SalesOrderHeader soh 
    ON sp.BusinessEntityID = soh.SalesPersonID
GROUP BY pp.LastName, sp.BusinessEntityID, soh.OrderDate;

当前结果,每个销售人员得到不同的排列,但是我希望每个销售人员有 4 个结果,每个 FQ 有 1 个。

LastName     SalesPersonID     FY      FQ   FQSales  SalesSameLastYr
------------------------------------------------------------------
Alberts          283          NULL     1   NULL      NULL
Alberts          283          NULL     1    NULL     32344.342
Alberts          283          NULL     3   NULL      NULL
Alberts          283          2013     2   342432      NULL
Alberts          283          NULL     4    NULL     32344.342
Alberts          283          NULL     3   NULL      NULL
Alberts          283          NULL     4    NULL     32344.342
Alberts          283          2013     2   436346      NULL

想要的结果:

LastName  SalesPersID   FY   FQ FQSales SalesSameLastYr Change Change%
-----------------------------------------------------------------------
Alberts      283       2013   1  2000     1900           100      5
Alberts      283       2013   2  2200     2000           200      10
Alberts      283       2013   3  2000     2100          -100     -5
Alberts      283       2013   4  3000     2850           150      5
Mathews      291       2013   1  2000     1900           100      5
Mathews      291       2013   2  2200     2000           200      10
Mathews      291       2013   3  2000     2100          -100     -5
Mathews      291       2013   4  3000     2850           150      5

你首先应该将数据分成两个表,一个代表每一年,计算每个表的 FY 和 FQ。:

SELECT pp.LastName, sp.BusinessEntityID AS SalesPersonID,'2013' as FY,
    CASE 
      WHEN MONTH(soh.OrderDate) BETWEEN 7 AND 9 THEN '1'
      WHEN MONTH(soh.OrderDate) BETWEEN 10 AND 12 THEN '2'
      WHEN MONTH(soh.OrderDate) BETWEEN 1 AND 3 THEN '3'
      WHEN MONTH(soh.OrderDate) BETWEEN 4 AND 6 THEN '4'
    END AS FQ,
    soh.SubTotal
into #tmpCurrentYear
FROM Sales.SalesPerson sp
INNER JOIN Person.Person pp ON sp.BusinessEntityID = pp.BusinessEntityID
INNER JOIN Sales.SalesOrderHeader soh ON sp.BusinessEntityID = soh.SalesPersonID
where soh.OrderDate between '2013-07-01' AND '2014-06-30'

SELECT pp.LastName, sp.BusinessEntityID AS SalesPersonID,'2012' as FY,
    CASE 
      WHEN MONTH(soh.OrderDate) BETWEEN 7 AND 9 THEN '1'
      WHEN MONTH(soh.OrderDate) BETWEEN 10 AND 12 THEN '2'
      WHEN MONTH(soh.OrderDate) BETWEEN 1 AND 3 THEN '3'
      WHEN MONTH(soh.OrderDate) BETWEEN 4 AND 6 THEN '4'
    END AS FQ,
    soh.SubTotal
into #tmpLastYear
FROM Sales.SalesPerson sp
INNER JOIN Person.Person pp ON sp.BusinessEntityID = pp.BusinessEntityID
INNER JOIN Sales.SalesOrderHeader soh ON sp.BusinessEntityID = soh.SalesPersonID
where soh.OrderDate between '2012-07-01' AND '2013-06-30' 

然后加入他们并在没有 orderDate 的情况下进行分组,否则它将为每个日期创建一行:

select t.LastName, t.SalesPersonID,t.FY,t.FQ, sum(t.SubTotal) as FQSales,         
sum(ly.SubTotal) as SalesSameLastFQ, sum(t.SubTotal)-sum(ly.SubTotal) as Change, 
      (sum(t.SubTotal)-sum(ly.SubTotal))/(sum(t.SubTotal)) as ChangePercentage
from #tmpCurrentYear as t
    INNER JOIN  #tmpLastYear as ly ON t.LastName = ly.LastName and t.BusinessEntityID = ly.BusinessEntityID and t.FQ = ly.FQ
group by t.LastName, t.SalesPersonID,t.FY,t.FQ

使用条件聚合:

SELECT pp.LastName, sp.BusinessEntityID AS SalesPersonID,
       v.FY, v.FQ,
       SUM(CASE WHEN FY = 2012 THEN soh.SubTotal END) as FY_prev,
       SUM(CASE WHEN FY = 2013 THEN soh.SubTotal END) as FY_curr,
       ( SUM(CASE WHEN FY = 2013 THEN soh.SubTotal END) /
         SUM(CASE WHEN FY = 2012 THEN soh.SubTotal END)
       ) - 1 as percent
FROM Sales.SalesPerson sp INNER JOIN
     Person.Person pp
     ON sp.BusinessEntityID = pp.BusinessEntityID INNER JOIN
     Sales.SalesOrderHeader soh
     ON sp.BusinessEntityID = soh.SalesPersonID CROSS APPLY
     (VALUES ((CASE WHEN MONTH(soh.OrderDate) BETWEEN 7 AND 9 THEN '1'
                    WHEN MONTH(soh.OrderDate) BETWEEN 10 AND 12 THEN '2'
                    WHEN MONTH(soh.OrderDate) BETWEEN 1 AND 3 THEN '3'
                    WHEN MONTH(soh.OrderDate) BETWEEN 4 AND 6 THEN '4'
               END),
              (CASE WHEN MONTH(soh.OrderDate) < 7 THEN YEAR(soh.OrderDate)
                    ELSE YEAR(soh.OrderDate) + 1
               END)
              )
     ) v(FQ, FY)
WHERE FY IN (2013, 2012)
GROUP BY pp.LastName, sp.BusinessEntityID, v.FY, v.FQ;

这使用 CROSS APPLY 来创造价值。这也可以通过 CTE 或子查询来完成。