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 |
+------+------+

列 b を列 a ごとに 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 のみを NULL 値で更新する (3 番目のレコードのみを更新する) 場合、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を参照してください


NULLbにある行のみを更新する場合、これは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;

私はそれがうまくいくと思います。良い形式ではありますが、接続が閉じられたときに tem2 が削除されるため、「ドロップ テーブル」は厳密には必要ありません。

于 2013-08-06T13:14:19.773 に答える