简体   繁体   English

SQL Server 2012更新中如何使用聚合函数

[英]How to use aggregate function in update in SQL server 2012

I Tried as shown below:我试过如下图:

CREATE TABLE #TEMP
(
ID INT,
EmpID INT,
AMOUNT INT
)

INSERT INTO #TEMP VALUES(1,1,10)
INSERT INTO #TEMP VALUES(2,1,5)
INSERT INTO #TEMP VALUES(3,2,6)
INSERT INTO #TEMP VALUES(4,3,8)
INSERT INTO #TEMP VALUES(5,3,10)
.
.
.

SELECT * FROM #TEMP

ID EmpID    AMOUNT
1   1       10
2   1       5
3   2       6
4   3       8
5   4       10  

UPDATE #TEMP
SET AMOUNT = SUM(AMOUNT) - 11
Where EmpID = 1

Expected Output: Table consists of employeeID's along with amount assigned to Employee I need to subtract amount from amount filed depending on employee usage.预期输出:表由员工 ID 以及分配给员工的金额组成,我需要根据员工使用情况从提交的金额中减去金额。 Amount "10" should be deducted from ID = 1 and amount "1" should be deducted from ID = 2.金额“10”应从 ID = 1 中扣除,金额“1”应从 ID = 2 中扣除。

Amount: Credits available for that particular employee depending on date.金额:根据日期可用于该特定员工的积分。

So i need to reduce credits from table depending on condition first i need to subtract from old credits.所以我需要根据条件从表中减少学分,首先我需要从旧的学分中减去。 In my condition i need to collect 11 rupees from empID = 1 so first i need to collect 10 rupee from ID=1 and 1 rupee from the next credit ie ID=2.在我的情况下,我需要从 empID = 1 收集 11 卢比,所以首先我需要从 ID=1 收集10卢比和从下一个信用(即 ID=2)收集1卢比。 For this reason in my expected output for ID=1 the value is 0 and final output should be like出于这个原因,在我预期的 ID=1 输出中,值为0 ,最终输出应该是这样的

ID EmpID    AMOUNT
1   1       0
2   1       4
3   2       6
4   3       8
5   4       10  

Need help to update records.需要帮助更新记录。 Check error in my update statement.检查我的更新语句中的错误。

I think you want the following: subtract amounts from 11 while remainder is positive.我认为您需要以下内容:从11减去金额,而余数为正数。 If this is true, here is a solution with recursive cte :如果这是真的,这里有一个递归cte的解决方案:

DECLARE @t TABLE ( id INT, amount INT )

INSERT  INTO @t VALUES  
( 1, 10 ),
( 2, 5 ),
( 3, 3 ),
( 4, 2 );

WITH    cte
          AS ( SELECT   * , 17 - amount AS remainder
               FROM     @t
               WHERE    id = 1
               UNION ALL
               SELECT   t.* , c.remainder - t.amount AS remainder
               FROM     @t t
                        CROSS JOIN cte c
               WHERE    t.id = c.id + 1 AND c.remainder > 0
             )
    UPDATE  t
    SET     amount = CASE WHEN c.remainder > 0 THEN 0
                          ELSE -remainder
                     END
    FROM    @t t
            JOIN cte c ON c.id = t.id

SELECT  * FROM    @t

Output:输出:

id  amount
1   0
2   0
3   1
4   2

Here I use 17 as start remainder.这里我用17作为起始余数。

If you use sql server 2012+ then you can do it like:如果您使用sql server 2012+那么您可以这样做:

WITH    cte
          AS ( SELECT   * ,
                        17 - SUM(amount) OVER ( ORDER BY id ) AS remainder
               FROM     @t
             )
    SELECT  id ,
            CASE WHEN remainder >= 0 THEN 0
                 WHEN remainder < 0
                      AND LAG(remainder) OVER ( ORDER BY id ) >= 0
                 THEN -remainder
                 ELSE amount
            END
    FROM    cte
Declare @Deduct int = -11, 
@CurrentDeduct int = 0 /*this represent the deduct per row */
update #TEMP 
        set   @CurrentDeduct = case when abs(@Deduct) >= AMOUNT then Amount else abs(@Deduct) end 
             , @Deduct = @Deduct + @CurrentDeduct
            ,AMOUNT = AMOUNT - @CurrentDeduct
    where EmpID= 1

First you should get a cumulative sum on amount:首先,您应该获得金额的累计金额:

select 
  id, 
  amount,
  sum(amount) over (order by id) running_sum 
from #TEMP;

From here we should put 0 on rows before running_sum exceeds the value 11. Update the row where the running sum exceeds 11 and do nothing to rows after precedent row.从这里开始,我们应该在 running_sum 超过值 11 之前将 0 放在行上。更新运行总和超过 11 的行,并对前一行之后的行不做任何处理。

select 
id,
amount
running_sum,
min(case when running_sum > 11 then id end) over () as decide
from (

    select 
      id, 
      amount,
      sum(amount) over (order by id) running_sum 
    from #TEMP

);

From here we can do the update:从这里我们可以进行更新:

merge into #TEMP t
using (    
    select 
      id,
      amount
      running_sum,
      min(case when running_sum > 11 then id end) over () as decide
    from (
        select 
          id, 
          amount,
          sum(amount) over (order by id) running_sum 
        from #TEMP
        )
    )a  on a.id=t.id
when matched then update set 
  t.amount = case when a.id = a.decide then a.running_sum - 11
                  when a.id < a.decide then 0
                  else a.amount 
             end;

See an SQLDFIDDLE查看SQLDFIDDLE

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在SQL Server 2012中按汇总功能检索数据 - How to retrieve data with group by aggregate function in SQL Server 2012 如何在SQL Server 2012中使用转换功能? - How to use convert function in SQL Server 2012? SQL Server 2012:在聚合函数中与over子句不同 - SQL Server 2012: distinct with over clause in an aggregate function 如何使用SQL Server 2012窗口函数完成查询? - How to use a SQL Server 2012 Window Function to accomplish my query? Sql Server:如何在WHERE子句中使用像MAX这样的聚合函数 - Sql Server : How to use an aggregate function like MAX in a WHERE clause 使用PIVOT的动态列,我需要使用这些动态列以及聚合函数来按月生成报表-SQL Server 2012 - Dynamic columns using PIVOT and I need to use those dynamic columns along with aggregate function to generate reports month wise -SQL Server 2012 无法在包含聚合或子查询SQL Server 2012的表达式上执行聚合功能 - Cannot perform an aggregate function on an expression containing an aggregate or a subquery sql server 2012 无法对包含聚合或子查询的表达式执行聚合功能。 SQL Server 2012 - Cannot perform an aggregate function on an expression containing an aggregate or a subquery. SQL Server 2012 如果我们需要在SQL Server 2014中聚合特定行时如何使用聚合函数 - How to use aggregate function if we need aggregate of specific rows in SQL Server 2014 SQL Server中的聚合函数 - Aggregate function in SQL Server
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM