【问题标题】:Average of last n or 10 rows only in SQL Server仅在 SQL Server 中最后 n 或 10 行的平均值
【发布时间】:2014-07-09 19:55:12
【问题描述】:

我有一个查询结果集。假设它包含 100 行,2 列。我想要第三个计算列作为最后 10 行的平均值。像这样:

Hours     Pay    Last10Avg
--------------------------
10      1
20      2
30      3
40      4
50      5
60      6
70      7  
80      8
90      9
100     10   (550/55)= 10
110     11
...       
200     20    (1550/155) = 10

因此,对于每 10 行,我基本上想取平均值。我的意思是1到10平均。 11到20平均。我如何得到它(在这个例子中,每 10 行的值 '10')?

其他信息:

550 = 10+20+..100
55 = 1+2+..10
1550 = 110+120+...200
155 = 10+11+...20

【问题讨论】:

  • 查找LAG函数

标签: sql-server average


【解决方案1】:

这就是范围分区的作用。如果您使用的是 SQL Server 2012 或更高版本,您只需执行以下操作:

select hours, pay,
       (sum(hours) over (order by hours range between 9 preceding and current row) /
        sum(pay) over (order by hours range between 9 preceding and current row)
       ) as thirdcol
from table t;

这会将移动平均线放在每一行上,因此它与问题的格式不完全相同,但它似乎更有用。

【讨论】:

    【解决方案2】:

    您可以按FLOOR(ROWNUMBER/10) 对数据进行分区以计算该平均值。

    查询示例:

    SELECT 
        T.Hours,
        T.Pay, 
        -- Use case to count avg only for 1 out of 10 rows
        CASE WHEN Idx % 10 = 0 THEN AVG(Hours/Pay) 
            OVER (PARTITION BY FLOOR((Idx-1)/10)) ELSE NULL END Avg
    
    FROM (
        SELECT 
            T.Hours,
            T.Pay, 
            -- In order by specify order you need, use (SELECT 0) to keep db order
            ROW_NUMBER() OVER (ORDER BY (SELECT 0)) Idx
        FROM [YourTable] T
    ) T
    

    工作样本:http://sqlfiddle.com/#!6/d41d8/20091

    【讨论】:

    • 您拥有示例查询中的所有内容 - 它是行号。
    • 我在 OVER(分区... .(问题“image for sql”的第一行)
    • 我在看你的小提琴最后 10 行 (11...0),(5..14) 它应该是 495/95= 5.2。但是您的值显示为 4。我还用实际的 AVG(/) 替换了 1。显示了一些结果,但它不正确。
    • 我计算的是 AVG 而不是 SUM(Hours)/SUM(Pay),这样结果就不同了。试试这个:sqlfiddle.com/#!6/d41d8/20128。我也没有看到 CTE 的问题:sqlfiddle.com/#!6/d41d8/20131
    【解决方案3】:

    只是一个非 2012 年的解决方案。

    DECLARE @PageSize INTEGER;
    
    SET @PageSize = 10;
    
    WITH cteRanked
    AS
    (
        SELECT      ROW_NUMBER() OVER (ORDER BY Hours) AS RID,
                    ROW_NUMBER() OVER (ORDER BY Hours) % @PageSize AS ModValue,
                    Hours,
                    Pay
        FROM        Table1
    ),
    cteWindows
    AS
    (
        SELECT      r1.RID AS StartRID,
                    r2.RID AS EndRID
        FROM        cteRanked r1 INNER JOIN cteRanked r2
                    ON  r1.RID = r2.RID - (@PageSize - 1)
        WHERE       r1.ModValue = 1
    )
    
    SELECT      r.Hours,
                r.Pay,
                SUM(r2.Hours) / SUM(r2.Pay) AS Last10Avg
    FROM        cteRanked r LEFT JOIN cteWindows w
                ON  r.RID = w.EndRID
                LEFT JOIN cteRanked r2
                ON  r2.RID BETWEEN w.StartRID AND w.EndRID
    GROUP BY    r.Hours,
                r.Pay
    ORDER BY    r.Hours,
                r.Pay;
    

    【讨论】:

      【解决方案4】:

      试试这个, 用于最后 N(4) 条记录的平均值

      with cte (a,b) as
      (
      select sum(hours),sum(pay) from mytable
      where Hours not in(
      select top (
      (select COUNT(*) from
       mytable)-4
      )Hours from mytable)
      )
      select a/b from cte;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-17
        • 2023-03-24
        相关资源
        最近更新 更多