6

我在 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:如果我只想用NULL值更新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;
4

3 回答 3

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


如果您只想更新bNULL列中的行,这只是子句的问题: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;

http://sqlfiddle.com/#!2/31ffb/1

于 2013-08-06T13:23:05.930 回答
1

JOIN把它写成一个

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 ;
于 2013-08-06T13:26:03.683 回答
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 无论如何都会在连接关闭时被删除,尽管它是一种很好的形式。

于 2013-08-06T13:14:19.773 回答