如何在 UPDATE 中避免 GROUP BY 或 DISTINCT
How to avoid GROUP BY or DISTINCT in UPDATE
我有一个table这样的
A B C D E F
00002471 Sd3a28d471 0 24.00 377.500000 1
00002471 Sd3a28d471 0 353.50 377.500000 1
00002471 Sd3a28d471 1 211.00 211.000000 1
00002471 Sd3a28e471 1 343.00 343.000000 1
00002471 Sd3a28e471 0 56.00 242.370000 1
00002471 Sd3a28e471 0 177.06 242.370000 1
00002471 Sd3a28e471 0 9.31 242.370000 1
00002471 Sd3a28f471 0 10.31 10.31 1
00002471 Sd3a28f471 1 10.31 10.31 1
通过对 A、B 和 C 列进行分组,我需要检查哪一个列在 E 中具有最低值,并将最低值行的 F 列更新为 1,将其余列更新为 0。如果值相同我需要将 F 列更新为 1,其中 C 为 1。我需要的输出如下
A B C D E F
00002471 Sd3a28d471 0 24.00 377.500000 0
00002471 Sd3a28d471 0 353.50 377.500000 0
00002471 Sd3a28d471 1 211.00 211.000000 1
00002471 Sd3a28e471 1 343.00 343.000000 0
00002471 Sd3a28e471 0 56.00 242.370000 1
00002471 Sd3a28e471 0 177.06 242.370000 1
00002471 Sd3a28e471 0 9.31 242.370000 1
00002471 Sd3a28f471 0 10.31 10.31 0
00002471 Sd3a28f471 1 10.31 10.31 1
我试过下面的查询
UPDATE T1
SET T1.F = CASE WHEN T1.E <= T2.E THEN 1 ELSE 0 END
--select t2.*
FROM
(SELECT DISTINCT A,B,C,D,E,F FROM #SalesOrder WHERE E IS NOT NULL) T1
INNER JOIN
(SELECT DISTINCT A,B,C,D,E,F FROM #SalesOrder WHERE E IS NOT NULL) T2
ON T1.A = T2.A
AND T1.B = T2.B
--AND T1.C = T2.C
WHERE T1.C = 1 AND T2.C = 0
但是这个查询会抛出一个错误
Error Message
Msg 4418, Level 16, State 1, Line 265
Derived table 'T1' is not updatable because it contains aggregates, or a DISTINCT or GROUP BY clause, or PIVOT or UNPIVOT operator.
@Suresh Gajera
我需要取 A、B、C 和 E 的不同值,取不同的值后会像这样
A B C E
00002471 Sd3a28d471 0 377.500000
00002471 Sd3a28d471 1 211.000000
00002471 Sd3a28e471 0 242.370000
00002471 Sd3a28e471 1 343.000000
00002471 Sd3a28f471 0 10.31
00002471 Sd3a28f471 1 10.31
在此之后我需要根据 C 列比较 E 的值,在此第二行与第一行相比最低,因此第二行应为 1,第一行应为 0...在应该更新第三行和第四行。在这种情况下,当涉及到第 5 行和第 6 行时,值相同,我需要将 F 列更新为 1,其中 C 为 1
只有按 A 和 B 分组(不按 C),您的预期结果才有意义。
在这种情况下:
update t
set t.f = case when t.e = tt.mine then 1 else 0 end
from tablename t inner join (
select a, b, min(e) mine
from tablename
group by a, b
) tt
on tt.a = t.a and tt.b = t.b
参见demo。
或者使用 CTE
和 window 函数 MIN()
:
with cte as (
select *, min(e) over (partition by a, b) mine
from tablename
)
update cte
set f = case when e = mine then 1 else 0 end
参见demo。
结果:
> A | B | C | D | E | F
> ---: | :--------- | -: | --: | :----- | -:
> 2471 | Sd3a28d471 | 0 | 24 | 377.50 | 0
> 2471 | Sd3a28d471 | 0 | 353 | 377.50 | 0
> 2471 | Sd3a28d471 | 1 | 211 | 211.00 | 1
> 2471 | Sd3a28e471 | 1 | 343 | 343.00 | 0
> 2471 | Sd3a28e471 | 0 | 56 | 242.37 | 1
> 2471 | Sd3a28e471 | 0 | 177 | 242.37 | 1
> 2471 | Sd3a28e471 | 0 | 9 | 242.37 | 1
我有一个table这样的
A B C D E F
00002471 Sd3a28d471 0 24.00 377.500000 1
00002471 Sd3a28d471 0 353.50 377.500000 1
00002471 Sd3a28d471 1 211.00 211.000000 1
00002471 Sd3a28e471 1 343.00 343.000000 1
00002471 Sd3a28e471 0 56.00 242.370000 1
00002471 Sd3a28e471 0 177.06 242.370000 1
00002471 Sd3a28e471 0 9.31 242.370000 1
00002471 Sd3a28f471 0 10.31 10.31 1
00002471 Sd3a28f471 1 10.31 10.31 1
通过对 A、B 和 C 列进行分组,我需要检查哪一个列在 E 中具有最低值,并将最低值行的 F 列更新为 1,将其余列更新为 0。如果值相同我需要将 F 列更新为 1,其中 C 为 1。我需要的输出如下
A B C D E F
00002471 Sd3a28d471 0 24.00 377.500000 0
00002471 Sd3a28d471 0 353.50 377.500000 0
00002471 Sd3a28d471 1 211.00 211.000000 1
00002471 Sd3a28e471 1 343.00 343.000000 0
00002471 Sd3a28e471 0 56.00 242.370000 1
00002471 Sd3a28e471 0 177.06 242.370000 1
00002471 Sd3a28e471 0 9.31 242.370000 1
00002471 Sd3a28f471 0 10.31 10.31 0
00002471 Sd3a28f471 1 10.31 10.31 1
我试过下面的查询
UPDATE T1
SET T1.F = CASE WHEN T1.E <= T2.E THEN 1 ELSE 0 END
--select t2.*
FROM
(SELECT DISTINCT A,B,C,D,E,F FROM #SalesOrder WHERE E IS NOT NULL) T1
INNER JOIN
(SELECT DISTINCT A,B,C,D,E,F FROM #SalesOrder WHERE E IS NOT NULL) T2
ON T1.A = T2.A
AND T1.B = T2.B
--AND T1.C = T2.C
WHERE T1.C = 1 AND T2.C = 0
但是这个查询会抛出一个错误
Error Message
Msg 4418, Level 16, State 1, Line 265
Derived table 'T1' is not updatable because it contains aggregates, or a DISTINCT or GROUP BY clause, or PIVOT or UNPIVOT operator.
@Suresh Gajera 我需要取 A、B、C 和 E 的不同值,取不同的值后会像这样
A B C E
00002471 Sd3a28d471 0 377.500000
00002471 Sd3a28d471 1 211.000000
00002471 Sd3a28e471 0 242.370000
00002471 Sd3a28e471 1 343.000000
00002471 Sd3a28f471 0 10.31
00002471 Sd3a28f471 1 10.31
在此之后我需要根据 C 列比较 E 的值,在此第二行与第一行相比最低,因此第二行应为 1,第一行应为 0...在应该更新第三行和第四行。在这种情况下,当涉及到第 5 行和第 6 行时,值相同,我需要将 F 列更新为 1,其中 C 为 1
只有按 A 和 B 分组(不按 C),您的预期结果才有意义。
在这种情况下:
update t
set t.f = case when t.e = tt.mine then 1 else 0 end
from tablename t inner join (
select a, b, min(e) mine
from tablename
group by a, b
) tt
on tt.a = t.a and tt.b = t.b
参见demo。
或者使用 CTE
和 window 函数 MIN()
:
with cte as (
select *, min(e) over (partition by a, b) mine
from tablename
)
update cte
set f = case when e = mine then 1 else 0 end
参见demo。
结果:
> A | B | C | D | E | F
> ---: | :--------- | -: | --: | :----- | -:
> 2471 | Sd3a28d471 | 0 | 24 | 377.50 | 0
> 2471 | Sd3a28d471 | 0 | 353 | 377.50 | 0
> 2471 | Sd3a28d471 | 1 | 211 | 211.00 | 1
> 2471 | Sd3a28e471 | 1 | 343 | 343.00 | 0
> 2471 | Sd3a28e471 | 0 | 56 | 242.37 | 1
> 2471 | Sd3a28e471 | 0 | 177 | 242.37 | 1
> 2471 | Sd3a28e471 | 0 | 9 | 242.37 | 1