平均值取决于来自其他列的累计值,即运行总计

时间:2015-11-14 22:26:50

标签: sql-server

我使用AVERAGE和Cumulative作为搜索词筛选了各种sql-server标记的线程。各种绝望的答案,但我无法将它们拼凑在一起以满足我的需求。用例是查找累计天数大于60且小于90的时间段的初始平均值(累计值/累计天数)。

下面是ID标识对象的表,VALUE是按月报告的数量,DAYSON是对象运行以生成值的月份中的天数。 YEARMONTH是可以排序的日期值。

ID  VALUE   DASYON  YEARMONTH
1    166      27    201502
1      1       2    201505
1    569      19    201507
1    312      19    201508
2    364      27    201502
2    328      31    201503
2    242      29    201504
2    273      31    201505
2    174      30    201506
2    188      25    201507
2    203      25    201508
3    474      28    201502
3    521      31    201503
3    465      30    201504
3    473      31    201505
3    434      30    201506
3    404      31    201507

我想创建一个汇总表,该汇总表将累计值除以累计天数大于60且小于90的每个ID的累计天数进行平均。下面是一个包含累计值的表。 (我在Excel中生成了这个)

ID  VALUE   cumValue    DASYON  cumDaysOn   YEARMONTH
1    166      166         27       27        201502
1      1      167          2       29        201505
1    569      736         19       48        201507
1    312     1048         19       67        201508
2    364      364         27       27        201502
2    328      692         31       58        201503
2    242      934         29       87        201504
2    273     1207         31      118        201505
2    174     1381         30      148        201506
2    188     1569         25      173        201507
2    203     1772         25      198        201508
3    474      474         28       28        201502
3    521      505         31       59        201503
3    465      535         30       89        201504
3    473      566         31      120        201505
3    434      596         30      150        201506
3    404      627         31      181        201507

我是基于其他线程尝试的:

    SELECT 
       ID, 
       Value, 
       SUM(Value) OVER (ORDER BY ID, YearMonth) [cumValue], 
       DaysOn, 
       SUM (DaysOn) OVER (Order by ID, YearMonth) as cumDaysOn, 
       YearMonth
    FROM table

WHERE DAYSON > 0 and Liquid > 0 and YearMonth > 201501
GROUP BY ID, YearMonth, Value, DaysOn
ORDER BY ID, yearmonth

我不能让它迭代ID;它只是总结列。如果我可以像上面那样创建一个表或视图,那么我总是可以使用select语句并将cumvalue除以cumdayson。

下面的表格显示了根据标准获得初始平均值(InititalAverageValue)的位置:

ID  VALUE   cumValue    DASYON  cumDaysOn   YEARMONTH   InitalAvgValue
1    166      166         27       27        201502
1      1      167          2       29        201505
1    569      736         19       48        201507
1    312     1048         19       67        201508           55
2    364      364         27       27        201502
2    328      692         31       58        201503
2    242      934         29       87        201504           32
2    273     1207         31      118        201505
2    174     1381         30      148        201506
2    188     1569         25      173        201507
2    203     1772         25      198        201508
3    474      474         28       28        201502
3    521      505         31       59        201503
3    465      535         30       89        201504           18
3    473      566         31      120        201505
3    434      596         30      150        201506
3    404      627         31      181        201507

最终我想要的是这样的表:

ID   InitalAvgValue 
1        55 
2        32 
3        18 

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

关键是你需要一个总计。有几种计算运行总计的方法,但它们在简单性和性能之间有各种权衡。 “最佳”方法取决于数据集的预期大小以及您使用的是SQL Server 2012还是早期版本。以下文章介绍了一些不同的选项以及优缺点:

http://sqlperformance.com/2012/07/t-sql-queries/running-totals

以下是使用相关子查询的快速示例,这对于小型数据集可能是合理的,但可能无法很好地扩展到较大的数据:

document.getElementsByClassName("arrow up login-required access-required")[0].click();

输出:

SELECT
    ID,
    ROUND(AVG(CAST(CumulativeValue AS FLOAT) / CAST(CumulativeDaysOn AS FLOAT)), 1) AS Average
FROM
    (
        SELECT
            ID,
            Value,
            DaysOn,
            (SELECT SUM(Value) FROM ExampleTable t2 WHERE t1.ID = t2.ID and t2.YearMonth <= t1.YearMonth) AS CumulativeValue,
            (SELECT SUM(DaysOn) FROM ExampleTable t2 WHERE t1.ID = t2.ID and t2.YearMonth <= t1.YearMonth) AS CumulativeDaysOn
        FROM
            ExampleTable t1
    ) AS ExampleWithTotals
WHERE
    CumulativeDaysOn > 60 AND CumulativeDaysOn < 90
GROUP BY
    ID
ORDER BY
    ID
;