根据另一列sql server中的不同行更新多个列

时间:2015-10-07 12:39:05

标签: sql sql-server sql-server-2008

我有一张桌子

 staff   Type    col1   col2  
    1     a       0      200
    1     b       50     2000
    1     c       2      200
    2     a       0      100
    2     b       25     1000
    2     c       2      200
    3     a       0      150
    3     b       35     1500
    3     c       2      200

我只是想知道我是否可以根据每位员工col1列中的值更新col2Type。我的更新逻辑将是例如员工1
更新col1,其中Type = a是200 /(2000/50)= 5
更新col1,其中Type = b为col1 - (200 /(2000/50))= 50-5 = 45
更新col2,其中Type = b是2000-200 = 1800
更新col2,其中Type = a到0

请查看我需要达到的结果如下:更新值(*)

staff   Type    col1   col2  
    1     a       5*      0*
    1     b       45*     1800*
    1     c       2      200
    2     a       2.5*    0*
    2     b       22.5*   900*
    2     c       2      200
    3     a       3.5*    0*
    3     b       31.5*   1350*
    3     c       2      200

是否可以在不使用游标/循环/函数/ ctes的情况下完成此操作?

2 个答案:

答案 0 :(得分:0)

尝试以下代码

    DECLARE @myTable TABLE (
  staff  INTEGER  NOT NULL
  ,Type   VARCHAR(1) NOT NULL
  ,col1   INTEGER  NOT NULL
  ,col2   INTEGER  NOT NULL
)
INSERT INTO @myTable VALUES(1,'a',0,200),
 (1,'b',50,2000),
 (1,'c',2,200),
(2,'a',0,100),
(2,'b',25,1000),
(2,'c',2,200),
 (3,'a',0,150),
(3,'b',35,1500),
(3,'c',2,200)


UPDATE t1
SET Col1  = CASE WHEN Type ='a' 
            THEN col2/(Select Col2/Col1 FROM @myTable T2 WHERE T2.Type = 'b' AND T2.staff = T1.Staff)
            WHEN Type ='b'
            THEN col1 - ((Select Col2 FROM @myTable T2 WHERE T2.Type = 'a' AND T2.staff = T1.Staff)/(Col2/Col1))
            ELSE COl1
            END ,
    Col2 =  CASE WHEN Type = 'b'
            THEN Col2 - (Select Col2 FROM @myTable T2 WHERE T2.Type = 'a' AND T2.staff = T1.Staff)
            WHEN Type = 'a'
            THEN 0
            Else Col2
            END
FROM @MyTable t1

SELECT * FROM @myTable

答案 1 :(得分:0)

你可以在一个大规模的查询中完成它,但是你可能需要很多故障保护来使它变得万无一失。例如,您可以在b:col1b:col2中考虑值0(虽然假设您只需要交叉乘法,但您可以执行a:col2 * {{ 1}} / b:col1除了少了一个例外之外,它对于计算机来说要简单得多(除非是混乱)。缺点是当你开始使用大量数字时,但是我会这样做。我会假设你不会超过1000000 ^ 2这样有点无关紧要。同样,我的代码会假设总有一行b:col2a行。

b

行为如下:如果类型declare @test as table( staff int, Type char(1), col1 decimal(6,2), col2 decimal(6,2) ) insert into @test values(1,'a',0,200); insert into @test values(1,'b',50,2000); insert into @test values(1,'c',2,200); insert into @test values(2,'a',0,100); insert into @test values(2,'b',25,1000); insert into @test values(2,'c',2,200); insert into @test values(3,'a',0,150); insert into @test values(3,'b',35,1500); insert into @test values(3,'c',2,200); UPDATE FirstTable SET FirstTable.col1 = CASE FirstTable.[type] WHEN 'a' THEN JoinedTable.col1 * FirstTable.col2 / JoinedTable.col2 ELSE FirstTable.col1 - FirstTable.col1 * JoinedTable.col2 / FirstTable.col2 END, FirstTable.col2 = CASE FirstTable.[type] WHEN 'a' THEN 0 ELSE FirstTable.col2 - JoinedTable.col2 END FROM @test FirstTable INNER JOIN @test JoinedTable ON FirstTable.staff = JoinedTable.staff AND JoinedTable.[Type] = CASE FirstTable.[Type] WHEN 'a' THEN 'b' ELSE 'a' END WHERE FirstTable.[Type] in('a','b') 的col2中有0,则崩溃。如果一个类型为ba的员工有多个行,我相信它会以非确定性的方式采用其中一个,这将导致一些非确定性和潜在错误的结果。如果没有类型ba,则会完全跳过员工。

否则(当它工作时),它只是根据类型更新类型为ba的行。在1个查询中同时更新允许您不使用临时表等,因为新数据不会覆盖旧数据,直到完成整个查询。

另外,尽量不要在列中使用b之类的关键字,否则最终可能会出现一些错误。