【问题标题】:sql server running total with over, partitionsql server 运行总数超过,分区
【发布时间】:2014-05-03 21:15:11
【问题描述】:

我正在尝试在以下查询中计算运行总计

select 
    a.ICode, MONTH(a.VDate), YEAR(a.vdate)
    , sum(isnull(a.qty, 0))
    , sum(isnull(a.qty, 0)) OVER (partition by a.icode order by a.icode) AS 'total' 
from 
    t_Stock as a
group by 
    a.ICode, MONTH(a.VDate), YEAR(a.vdate)
order by 
    a.icode, YEAR(a.vdate), MONTH(a.VDate)

但我收到一个错误:

消息 8120,第 16 级,状态 1,第 3 行
列“t_Stock.Qty”在选择列表中无效,因为它既不包含在聚合函数中,也不包含在 GROUP BY 子句中。

为什么't_Stock.Qty'需要在GROUP BY子句中,因为我已经在使用聚合函数(Sum(a.Qty))

一些演示数据:

icode   vtype   qty   vdate 
32114   Sales   -2    2013-06-03 18:09:17.953 
33459   Sales   -1    2013-06-03 19:39:59.843 
34446   Sales   -1    2013-06-03 20:46:17.030 
39914   Tra     -3    2014-01-07 13:02:31.000
30899   Sales   -1    2013-06-04 11:48:06.267 
25676   Sales   -3    2013-06-04 17:34:01.470 
32126   Sales   -1    2013-06-04 18:12:44.267 
34688   Sales   -1    2013-06-04 18:40:52.750 
31550   Sales   -1    2013-06-04 19:26:40.937 
32795   Sales   -1    2013-06-05 12:03:00.250 

【问题讨论】:

  • @M.Ali ,我选择了真正解决问题的答案,其余我没有。

标签: sql sql-server sql-server-2012


【解决方案1】:

使用聚合的窗口函数时,实际上需要嵌套结果。这是您的查询的一个版本,应该可以工作:

select a.ICode, MONTH(a.VDate), YEAR(a.vdate),
       sum(isnull(a.qty, 0)),
       sum(sum(isnull(a.qty, 0))) OVER (partition by a.icode order by a.icode) AS total
from t_Stock a
group by a.ICode, MONTH(a.VDate), YEAR(a.vdate)
order by a.icode, YEAR(a.vdate), MONTH(a.VDate);

我不确定你打算用这个做什么。让order by 包含与partition by 相同的值是不寻常的。我希望是这样的:

select a.ICode, MONTH(a.VDate), YEAR(a.vdate),
       sum(isnull(a.qty, 0)),
       sum(sum(isnull(a.qty, 0))) OVER (partition by a.icode
                                        order by year(a.vdate), month(a.vdate)
                                       ) AS total
from t_Stock a
group by a.ICode, MONTH(a.VDate), YEAR(a.vdate)
order by a.icode, YEAR(a.vdate), MONTH(a.VDate);

【讨论】:

    【解决方案2】:

    写成:

    select a.ICode,MONTH(a.VDate), YEAR(a.vdate)
    , sum(isnull(a.qty,0)) OVER(partition by a.icode order by a.icode)
      AS 'Runningtotal'
    , sum(isnull(a.qty,0)) OVER(partition by a.icode,MONTH(a.VDate), YEAR(a.vdate) 
      order by a.icode,YEAR(a.vdate),MONTH(a.VDate)) AS 'total' 
    from 
    t_Stock as a
    --group by a.ICode ,MONTH(a.VDate), YEAR(a.vdate)
    order by a.icode,YEAR(a.vdate),MONTH(a.VDate)
    

    【讨论】:

    • 我之前试过这个查询,执行起来需要很多时间。
    • 请从您的表 t_Stock 中发布一些数据,这样会更容易解释为什么需要两个窗口函数来获得这些总数
    • 这也不会得到相同的结果 - 假设t_stock 中有多行,您的版本将保留它们,而(尝试)原始版本不会。 @NitinKabra - 至少部分速度问题是YEAR()MONTH() 可能会强制进行表扫描(删除使用任何索引来获取VDate)。是的,请给我们提供起始数据和期望的结果。
    • 我在问题中复制了几行。抱歉表格的格式。
    • ok ..specify 你的意思是什么意思是运行总计对于给定的月份和年份你想要合格 iCodes 的总数?因为给出错误的第二个窗口函数实际上是处理在 Groupby 中创建的组,而不是处理 t_Stock 表的单个行
    【解决方案3】:

    为什么 't_Stock.Qty' 需要在 GROUP BY 子句中,因为我已经在使用聚合函数 (Sum(a.Qty))?

    出现此问题是因为您使用“SUM(something)”然后您使用“SUM(something) over(partition by...)”

    当您使用“SUM(something)”时,您将需要“group by ...”子句 但是当你使用“SUM(something) over(partition by...)”时,它不接受/不需要“group by..”子句 http://technet.microsoft.com/en-us/library/ms189461.aspx


    在它们之间选择一个。

    如果您想同时使用它们,请尝试以下查询:

    select a.ICode,MONTH(a.VDate) as 'month', YEAR(a.vdate) as 'year'
    , bb.xtotal
    ,sum(isnull(a.qty,0)) OVER (partition by a.icode order by a.icode) AS 'total' 
    from 
    @temp a
    inner join
    (
     select b.ICode, b.vdate,
        sum(isnull(b.qty,0)) as xtotal
     from @temp b 
     group by b.Icode, b.vdate
    ) bb on a.Icode = bb.Icode and bb.vdate = a.vdate
    order by a.icode,YEAR(a.vdate),MONTH(a.VDate)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-13
      • 2018-03-30
      • 1970-01-01
      • 1970-01-01
      • 2019-03-19
      • 1970-01-01
      • 1970-01-01
      • 2020-06-09
      相关资源
      最近更新 更多