我在MYSQL中有一个表:
CREATE TABLE test.tem(a INT,b INT);
以下数据:
INSERT INTO test.tem VALUES(1,2),(1,1),(1,NULL),(2,3);
现在数据应该是:
+------+------+
| a | b |
+------+------+
| 1 | 2 |
| 1 | 1 |
| 1 | NULL |
| 2 | 3 |
+------+------+
我想按列a。将列b更新到min(b)组。
所以SQL应该是:
UPDATE test.tem o
SET o.b = (SELECT
MIN(b)
FROM test.tem i
WHERE i.a = o.a)
但是MYSQL 无法在FROM子句中指定更新目标表
所以我认为下面的SQL可以很好地解决我的问题:
UPDATE test.tem t1
JOIN test.tem t2
ON t1.a = t2.a
SET t1.b = t2.b
WHERE t1.b IS NULL
OR t1.b > t2.b;
但结果是:
+------+------+
| a | b |
+------+------+
| 1 | 1 |
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
+------+------+
实际上我需要的结果是:
+------+------+
| a | b |
+------+------+
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 2 | 3 |
+------+------+
问题1:为什么MYSQL使用SQL计算出错误的结果?具有高效率的正确SQL应该是什么? 问题2:如果我只想用b值更新b(仅更新第三条记录),SQL应该是什么?
关于问题2,我试图使用下面不正确的SQL:
UPDATE test.tem t1
JOIN test.tem t2
ON t1.a = t2.a
AND t1.b IS NULL
SET t1.b = t2.b
WHERE t1.b IS NULL
OR t1.b > t2.b;
答案 0 :(得分:3)
您没有唯一列来标识行。因此,您的JOIN
可能会按照您的想法更新更多行。
你可能想要这样的东西:
UPDATE tem AS t1 JOIN (SELECT a, MIN(b) AS m FROM tem GROUP BY a) AS t2
USING (a)
SET t1.b = t2.m;
请参阅http://sqlfiddle.com/#!2/c6a04/1
如果您只想更新 b 列中NULL
的行,这只是WHERE
子句的问题:
CREATE TABLE tem(a INT,b INT);
INSERT INTO tem VALUES(1,2),(1,1),(1,NULL),(2,3);
UPDATE tem AS t1 JOIN (SELECT a, MIN(b) AS m FROM tem GROUP BY a) AS t2
USING (a)
SET t1.b = t2.m
WHERE t1.b IS NULL;
答案 1 :(得分:1)
UPDATE tem
JOIN ( SELECT a, MIN(b) AS min_b FROM tem GROUP BY a ) AS mins USING (a)
SET tem.b = mins.min_b ;
答案 2 :(得分:0)
您可以使用临时表来执行此操作:
create temporary table tem2 (a INT, b INT);
insert into tem2
select a, min(b) from tem group by a;
update tem
inner join tem2 on tem.a = tem2.a
set tem.b = tem2.b;
drop table tem2;
我认为这应该有效。 'drop table'并不是绝对必要的,因为tem2在连接关闭时会被丢弃,尽管它的形式很好。