我的表格如下所示
ID | action | flag
1 | A | 1
1 | A | 1
1 | B | 1
2 | A | 1
2 | A | 1
2 | B | 1
2 | B | 1
我想执行以下操作:如果对于相同的 ID ,操作列中的值 B 将显示为 1以上时间,然后我想将此 ID 的标志列设置为 0 。
结果应如下所示:
ID | action | flag
1 | A | 1
1 | A | 1
1 | B | 1
2 | A | 0
2 | A | 0
2 | B | 0
2 | B | 0
我知道有两种方法可以做到这一点:
join
临时表与原始表一起找到 ID ,我将为其设置 flag 到 0 除了上面解释的两个选项之外还有其他选择吗?理想情况下在一个查询中(没有子查询,没有临时查找表)。我在想JOIN
之类的内容,其中JOIN
子句包含GROUP BY
和HAVING
之类的内容,但直到现在我还没有成功..
答案 0 :(得分:3)
将原始表更新连接到使用聚合来标识候选ID
值的子查询是最快的方式:
UPDATE t1
SET flag = 0
FROM yourTable t1
INNER JOIN
(
SELECT ID
FROM yourTable
GROUP BY ID
HAVING SUM(CASE WHEN action = 'B' THEN 1 ELSE 0 END) > 1
) t2
ON t1.ID = t2.ID
请注意,此子查询不相关,这意味着SQL Server将仅对整个UPDATE
执行一次。因此,它并没有你想象中那么大的惩罚。
如果您创建了正式的查找表,理论上您可以在连接列中添加索引,这可能会使UPDATE
更快。但是创建和维护查找表有一个麻烦。在制作中,我宁愿使用一个查询来进行更新。
答案 1 :(得分:3)
这样的事情对你有用:
UPDATE t
SET flag = 0
FROM Table t
INNER JOIN
(
SELECT Id
FROM Table
WHERE action = 'B'
GROUP BY Id
HAVING COUNT(*) > 1
) d ON t.Id = d.Id