【问题标题】:Year to date running total column based on values within a row基于行内值的年初至今运行总计列
【发布时间】:2016-08-31 14:48:03
【问题描述】:

我在使用 SQL Azure 的数据库中进行了查询,该查询逐月返回一组办公室和这些办公室内的员工的一组销售数据,如下图所示: 返回此的查询称为 vwOfficeAndNegSalesTotals,如下所示:

选择办公室ID, DATENAME(Month,PipelineDate) + ' ' + DATENAME(Year,PipelineDate) as [PipelineMonth], 办公室名称, 谈判者, 状态, SUM(Fee) 作为 FeeValue 来自 vwBankingProjections 按 OfficeID 分组, DATENAME(Month,PipelineDate) + ' ' + DATENAME(Year,PipelineDate), 办公室名称, 谈判者, 状态, DATEPART(月,管道日期), DATEPART(YEAR,PipelineDate)

我需要添加另一列,它为该行中的谈判者提供年初至今的 FeeValue 总计,其中“迄今为止”的年份意味着直到并包括该行的月份。此外,它应该只计算状态为 Payment received 的 FeeValue。

所以,它会返回如下内容:

从 vwOfficeAndNegSalesTotals 的结构中可以看出,它所基于的查询 (vwBankingProjections) 确实包含实际日期,而不仅仅是文本 Month + Year - 这些日期在 PipelineDate 列中。

我的第一次尝试得到了当年的总数,查看 2016 年 5 月的一行(在撰写本文时)将是年初至今,但它只需要显示截至该日期提到的年份的总数行(因此,如果查看 2016 年 4 月的一行,则为 2016 年 1 月至 2016 年 4 月的总数)。如果它有任何帮助,这就是我想出的:

选择办公室ID, DATENAME(Year,PipelineDate) 作为 [PipelineYear], 办公室名称, 谈判者, SUM(Fee) 作为 YTDFee 来自 vwBankingProjections WHERE 状态(“已收到付款”) 按 OfficeID 分组, DATENAME(年,管道日期), 办公室名称, 谈判者

如果有人可以提供帮助,我将不胜感激,因为这超出了我的技能范围。

非常感谢

安德鲁

【问题讨论】:

    标签: sql sql-server tsql azure-sql-database


    【解决方案1】:

    您可以使用 SUM() OVER()。

    创建并填充表格。

    CREATE TABLE dbo.Sales
    (
        OfficeID int NOT NULL,
        PipelineMonth date NOT NULL
            CHECK (DAY(PipelineMonth) = 1),
        OfficeName nvarchar(25) NOT NULL,
        Negotiator nvarchar(25) NOT NULL,
        [Status] nvarchar(25) NOT NULL,
        FeeValue int NOT NULL,
        FeeValueReceived AS IIF([Status] = N'Payment received', FeeValue, 0)
    );
    GO
    
    INSERT INTO dbo.Sales (OfficeID, PipelineMonth, OfficeName, Negotiator, [Status], FeeValue)
        VALUES
        (1, '2016-01-01', N'London', N'Fred', N'Payment received', 5000),
        (1, '2016-01-01', N'London', N'Fred', N'Completed', 4800),
        (1, '2016-01-01', N'London', N'Kate', N'Payment received', 5980),
        (1, '2016-01-01', N'London', N'Kate', N'Completed', 7000),
        (1, '2016-01-01', N'London', N'Bob', N'Payment received', 9250),
        (2, '2016-01-01', N'Birmingham', N'Jo', N'Payment received', 7870),
        (2, '2016-01-01', N'Birmingham', N'Kathryn', N'Payment received', 3690),
        (2, '2016-01-01', N'Birmingham', N'Kathryn', N'Completed', 8545),
        (1, '2016-02-01', N'London', N'Fred', N'Payment received', 6500),
        (1, '2016-02-01', N'London', N'George', N'Completed', 2575),
        (1, '2016-02-01', N'London', N'George', N'Payment received', 7500),
        (1, '2016-02-01', N'London', N'Kate', N'Payment received', 8393),
        (1, '2016-02-01', N'London', N'Bob', N'Payment received', 6125);
    

    然后使用 SUM() OVER() 进行 SELECT 语句。

    SELECT OfficeID, PipelineMonth, OfficeName, Negotiator, [Status], FeeValue,
            SUM(FeeValueReceived) OVER (PARTITION BY OfficeID, Negotiator, YEAR(PipelineMonth) ORDER BY PipelineMonth, [Status] DESC, FeeValue DESC) AS 'YTD'
        FROM dbo.Sales
        ORDER BY PipelineMonth, OfficeID, Negotiator, [Status] DESC, FeeValue DESC
    

    参见联机丛书 > OVER 子句 (Transact-SQL):https://msdn.microsoft.com/en-us/library/ms189461.aspx

    【讨论】:

    • 太完美了——谢谢。我已经阅读了您发送的在线图书链接,虽然它确实有帮助,但我发现其中的某些内容真的很难理解。例如: _如果指定了 ROWS/RANGE 并且 用于 (短语法),则此规范用于窗口框架边界起点,CURRENT ROW 用于边界终点。例如,“ROWS 5 PRECEDING”等于“ROWS BETWEEN 5 PRECEDING 和当前行”。 _ 我确定我只是太密集了,但是您还有其他什么地方可以推荐我可以寻求帮助的地方吗?
    • 是的,抱歉,联机丛书并不总是那么容易。 OVER 子句乍一看相当复杂,尤其是 ROW OR RANGE 部分。请参阅 Itzik Ben-Gan 撰写的 Microsoft SQL Server 2012 T-SQL 基础 > 第 7 章:超越查询基础 > 窗口函数。
    • 他还写了一本后续书籍:Microsoft SQL Server 2012 High Performance T-SQL Using Windows Functions(开发人员参考)。我没有那个,但它可能很好。
    【解决方案2】:

    RichardCL 有一个可靠的方法。如果您需要真正的 RunningTotal,请参阅 https://devjef.wordpress.com/2012/10/20/calculating-running-totals/ 中的以下示例

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-25
      • 1970-01-01
      • 2021-11-07
      • 2013-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-19
      相关资源
      最近更新 更多