分组按月和季度和SUM前11个月

时间:2017-07-30 12:01:48

标签: sql sql-server

你好我现在一直在努力解决这个问题:/。我想要完成的是在同一个查询中返回月份值和本季度的前11个月。

所以我有一张桌子

CREATE TABLE Test
(
    Id INT,
    Date DATETIME2,
    Value DECIMAL(15,4)
)

我正在尝试获取以下数据:

          This Month   Previous_11_Months
January     100        1100
February    123        1123
March       211        2123

我的实际Sql:

DECLARE @endDate DATETIME2 = '6-30-2017',
    @plantId INT       = 1
DECLARE @endDateMinusYear DATETIME2 = DATEADD(YEAR,-1,@endDate),
        @firstDayOfThisQuarter DATETIME2,
        @firstDayOfThisQuarterLastYear DATETIME2

SELECT @firstDayOfThisQuarter = DATEADD(QQ, DATEDIFF(QQ , 0, @endDate), 0)
SELECT @firstDayOfThisQuarterLastYear = DATEADD(QQ, DATEDIFF(QQ , 0, @endDateMinusYear), 0)


SELECT
    DATENAME(MONTH, PlantPollutions.Date) AS MONTH,
    SUM(PlantPollutions.BurnerNaturalGas + PlantPollutions.OilHeaterNaturalGas) AS THIS_MONTH,
    (
    SELECT
            SUM(SubPlantPollutions.BurnerNaturalGas + SubPlantPollutions.OilHeaterNaturalGas)
        FROM PlantPollutions AS SubPlantPollutions
        WHERE SubPlantPollutions.Date >= DATEADD(MONTH, -11, PlantPollutions.Date)
        GROUP BY SubPlantPollutions.Date
    ) AS PREVIOUS_11_MONTHS
FROM PlantPollutions

WHERE PlantPollutions.PlantId = @plantId
  AND PlantPollutions.Date >= @firstDayOfThisQuarter

GROUP BY DATENAME(MONTH, PlantPollutions.Date)

当我在子查询WHERE SubPlantPollutions.Date >= DATEADD(MONTH, -11, PlantPollutions.Date) GROUP BY SubPlantPollutions.Date中注释时,它可以正常工作

2 个答案:

答案 0 :(得分:2)

窗口函数通常用于获取上一行或下一行值,例如使用lead()lag(),或聚合partition的值,或使用指定的{对行进行排名{1}}(order byrow_number()rank())。这利用了此行代码段{12}的12行(前11行和当前行)的特定窗口框架。dense_rank()

窗口函数对查询的结果集起作用,这就是使用按月聚合的派生表的原因。由于您只需要来自给定四分之一的行,因此再次嵌套查询(通过将前两个放在common table expression (cte)中),以便在{{{{{{}}时,您不想要的行中的值仍包含在窗口框架中计算出1}}。

有关窗口功能的更多信息,特别是窗口框架: Window Functions in SQL Server: Part 2-The Frame - Fabiano Amorim

更新了更新后问题的代码:

sum(ThisMonth) over (order by Month rows 11 preceding)

rextester演示:http://rextester.com/OBVR79198

sum()

在SQL Server 2012+中,您可以使用窗口函数将当前月份和前11个月的总和与派生表/子查询/ cte相加,declare @EndDate datetime2(0) = '20170630'; ;with cte as ( select Month , ThisMonth , Previous_11_Months = sum(ThisMonth) over (order by Month rows 11 preceding) from ( select Month = dateadd(month, datediff(month, 0, t.Date), 0) -- truncate date to month , ThisMonth = sum(Value) from dbo.Test t where t.Date >= dateadd(year, -1, dateadd(quarter, datediff(quarter, 0, @EndDate), 0)) group by dateadd(month, datediff(month, 0, t.Date), 0) -- truncate date to month ) s ) select MonthName = datename(Month,Month) , ThisMonth , Previous_11_Months from cte where month >= dateadd(quarter, datediff(quarter, 0, @EndDate), 0) 除以+-----------+-----------+--------------------+ | MonthName | ThisMonth | Previous_11_Months | +-----------+-----------+--------------------+ | April | 218 | 2291 | | May | 202 | 2312 | | June | 189 | 2357 | | July | 207 | 2335 | +-----------+-----------+--------------------+ ,如下所示:

Value

rextester演示:http://rextester.com/UTLDP89935

返回:

Month

答案 1 :(得分:0)

您可以非常轻松地获得前两列:

select datename(month, date) as mon,
       sum(case when dateadd(year, 1, date) > getdate()
                then value else 0 
           end) as this_month
from test t
group by datename(month, date)
order by min(date);

注意:如果您希望所有内容都基于月初,则“本月”的确切定义可能会有所不同,但这是理念。

对于第三列,您可以使用apply或相关子查询:

select datename(month, date) as mon,
       sum(value) as this_month,
       (select sum(t2.value)
        from test t2
        where t2.value >= dateadd(month, -11, min(t.date))
       ) as prev_11_months
from test t
where date >= dateadd(year, 1, getdate() )
group by datename(month, date)
order by min(date);