年度总计

时间:2019-02-01 21:04:30

标签: sql sql-server

尝试在查询中根据年份创建运行总计,因为我在查询中显示了最近3年的销售和佣金,并希望列出的每个销售人员的运行年度总计

尝试了各种方法来获取数据以执行此操作,但未能做到。

SELECT        TOP (100) PERCENT 'abc' AS CompanyCode, abc.AR_Salesperson.SalespersonName, abc.AR_SalespersonCommission.SalespersonDivisionNo, abc.AR_SalespersonCommission.SalespersonNo, 
                         SUM(abc.AR_SalespersonCommission.InvoiceTotal) AS InvoiceTotalSum, SUM(abc.AR_SalespersonCommission.CommissionAmt) AS CommissionAmtSum, DATENAME(month, abc.AR_SalespersonCommission.InvoiceDate) 
                         AS Month, DATENAME(year, abc.AR_SalespersonCommission.InvoiceDate) AS Year, DATEPART(m, abc.AR_SalespersonCommission.InvoiceDate) AS MonthNumber
FROM            abc.AR_Customer INNER JOIN
                         abc.AR_SalespersonCommission ON abc.AR_Customer.ARDivisionNo = abc.AR_SalespersonCommission.ARDivisionNo AND abc.AR_Customer.CustomerNo = abc.AR_SalespersonCommission.CustomerNo INNER JOIN
                         abc.AR_Salesperson ON abc.AR_SalespersonCommission.SalespersonDivisionNo = abc.AR_Salesperson.SalespersonDivisionNo AND 
                         abc.AR_SalespersonCommission.SalespersonNo = abc.AR_Salesperson.SalespersonNo
GROUP BY abc.AR_Salesperson.SalespersonName, abc.AR_SalespersonCommission.SalespersonDivisionNo, abc.AR_SalespersonCommission.SalespersonNo, DATENAME(month, abc.AR_SalespersonCommission.InvoiceDate), 
                         DATENAME(year, abc.AR_SalespersonCommission.InvoiceDate), DATEPART(m, abc.AR_SalespersonCommission.InvoiceDate)
HAVING        (DATENAME(year, abc.AR_SalespersonCommission.InvoiceDate) > DATEADD(year, - 3, GETDATE()))

UNION

SELECT        TOP (100) PERCENT 'XYZ' AS CompanyCode, xyz.AR_Salesperson.SalespersonName, xyz.AR_SalespersonCommission.SalespersonDivisionNo, xyz.AR_SalespersonCommission.SalespersonNo, 
                         SUM(xyz.AR_SalespersonCommission.InvoiceTotal) AS InvoiceTotalSum, SUM(xyz.AR_SalespersonCommission.CommissionAmt) AS CommissionAmtSum, DATENAME(month, xyz.AR_SalespersonCommission.InvoiceDate) 
                         AS Month, DATENAME(year, xyz.AR_SalespersonCommission.InvoiceDate) AS Year, DATEPART(m, xyz.AR_SalespersonCommission.InvoiceDate) AS MonthNumber
FROM            xyz.AR_Customer INNER JOIN
                         xyz.AR_SalespersonCommission ON xyz.AR_Customer.ARDivisionNo = xyz.AR_SalespersonCommission.ARDivisionNo AND xyz.AR_Customer.CustomerNo = xyz.AR_SalespersonCommission.CustomerNo INNER JOIN
                         xyz.AR_Salesperson ON xyz.AR_SalespersonCommission.SalespersonDivisionNo = xyz.AR_Salesperson.SalespersonDivisionNo AND 
                         xyz.AR_SalespersonCommission.SalespersonNo = xyz.AR_Salesperson.SalespersonNo
GROUP BY xyz.AR_Salesperson.SalespersonName, xyz.AR_SalespersonCommission.SalespersonDivisionNo, xyz.AR_SalespersonCommission.SalespersonNo, DATENAME(month, xyz.AR_SalespersonCommission.InvoiceDate), 
                         DATENAME(year, xyz.AR_SalespersonCommission.InvoiceDate), DATEPART(m, xyz.AR_SalespersonCommission.InvoiceDate)
HAVING        (DATENAME(year, xyz.AR_SalespersonCommission.InvoiceDate) > DATEADD(year, - 3, GETDATE()))

我希望在过去3年中,每个销售人员的输出将具有InvoiceTotalSum和CommissionAmt的总计。因此,当然,每个人的一月将是0,但是二月到十二月将是一个连续的总数

下面的样本数据和所需结果。期望的结果是突出显示的列

Sample Data and Desired Results

2 个答案:

答案 0 :(得分:0)

我要解决的两件事。

首先,我不确定为什么要在查询中使用UNION。我可以看到abcxyz之间的区别,但看起来仍然很奇怪。
您的查询肯定有可能被缩短/简化,这将需要更多信息来告知。

第二,我看不出一个有效的理由,为什么一月份的运行总计应该为0。
有关说明:

  • 2月(一年中的第二个月):预期结果中的运行总计包含2个月的金额
  • 3月:3个月
  • 4月:4个月
  • ...

所以一月应包含总运行1个月(​​一月本身)。

请尝试以下查询:

WITH MyData AS (
 <Please paste your query here>
)
SELECT CompanyCode, SalesPersonName, SalesPersonDivisionNo, InvoiceTotalSum,
SUM(InvoiceTotalSum) OVER (PARTITION BY SalesPersonDivisionNo, SalesPersonNo, SalesPersonName, Year ORDER BY MonthNumber) AS InvoiceTotalRunningSum,
CommissionAmtSum,
SUM(CommissionAmtSum) OVER (PARTITION BY SalesPersonDivisionNo, SalesPersonNo, SalesPersonName, Year ORDER BY MonthNumber) AS CommissionAmtRunningSum,
Month, Year, MonthNumber
FROM MyData
ORDER BY CompanyCode, SalesPersonDivisionNo, SalesPersonNo, SalesPersonName, Year, MonthNumber

魔术发生在PARTION BY / ORDER BY

答案 1 :(得分:0)

我认为您需要查看查询并简化查询。 一些注意事项:

  • 如果数据库中已经存在CompanyCode,请联接其表并将其与当前记录链接,而不是手动编写。
  • DATENAME(year, ... )的缩写为YEAR()
  • DATEPART(m, ...)的缩写为MONTH()
  • 我鼓励您使用别名
  • (DATENAME(year, xyz.AR_SalespersonCommission.InvoiceDate) > DATEADD(year, - 3, GETDATE()))将排除第一年并包括第一年。因此,2019-3 = 2016,您将获得2017、2018和2019,而您将获得2016、2017和2018。

供InvoiceTotalRunningSum使用:

SUM(InvoiceTotalSum) OVER (PARTITION BY SalespersonNo ORDER BY MonthNumber UNBOUNDED PRECEDING)

这会做上的累积总和InvoiceTotalSum对于每个SalespersonNo。您可以对每年,每月等的记录进行分区。只需添加更多分区即可,但是我将当前查询用作子查询,而是这样做了:

详细了解SELECT - OVER Clause (Transact-SQL)

尝试一下:

SELECT 
    'abc' AS CompanyCode
,   SalespersonName
,   SalespersonDivisionNo
,   SalespersonNo
,   InvoiceTotalSum 
,   SUM(InvoiceTotalSum) OVER (PARTITION BY SalespersonNo ORDER BY MonthNumber UNBOUNDED PRECEDING) InvoiceTotalRunningSum
,   CommissionAmtSum
,   SUM(CommissionAmtSum) OVER (PARTITION BY SalespersonNo ORDER BY MonthNumber UNBOUNDED PRECEDING) CommissionAmtRunningSum
,   [Month]
,   [Year]
,   MonthNumber
FROM (
    SELECT
        'abc' AS CompanyCode
    ,   ars.SalespersonName
    ,   arsc.SalespersonDivisionNo
    ,   arsc.SalespersonNo
    ,   SUM(arsc.InvoiceTotal) InvoiceTotalSum
    ,   SUM(arsc.CommissionAmt) CommissionAmtSum
    ,   DATENAME(month, arsc.InvoiceDate) [Month]
    ,   YEAR(arsc.InvoiceDate) [Year]
    ,   MONTH(arsc.InvoiceDate) MonthNumber
    FROM            
        abc.AR_Customer arc
    INNER JOIN abc.AR_SalespersonCommission  arsc ON arc.ARDivisionNo = arsc.ARDivisionNo AND arc.CustomerNo = arsc.CustomerNo 
    INNER JOIN abc.AR_Salesperson ars ON arsc.SalespersonDivisionNo = ars.SalespersonDivisionNo AND arsc.SalespersonNo = ars.SalespersonNo
    GROUP BY 
        ars.SalespersonName
    ,   arsc.SalespersonDivisionNo
    ,   arsc.SalespersonNo
    ,   YEAR(arsc.InvoiceDate)
    ,   MONTH(arsc.InvoiceDate)
    ,   DATENAME(month, arsc.InvoiceDate)
    HAVING    
        YEAR(arsc.InvoiceDate) BETWEEN YEAR(GETDATE()) - 3 AND YEAR(GETDATE()) - 1 -- Only include the last three years (excluding current year)
) D