質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

解決済

3回答

5593閲覧

MySQLでON DUPLICATE KEY UPDATEをした際に元々入っていた値を使い回したい

k725

総合スコア12

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

0グッド

0クリップ

投稿2016/11/01 03:13

編集2016/11/01 03:41

MySQLで下記のようなSQL文を実行した際に、思った結果とは違う結果になってしまいます。

SQL

1INSERT INTO 2 test(id, foo, bar, baz) 3VALUES 4 (1, 0, 0, 0) 5ON DUPLICATE KEY UPDATE 6 id = 1, 7 foo = foo + 1, 8 bar = foo + 1, 9 baz = bar + 1;

なお、test テーブルには以下のようなデータが入っています。

|id(A_I)|foo|bar|baz|
|--------------|
|1|1|1|1|

実行結果がこうなってしまいます。

|id(A_I)|foo|bar|baz|
|--------------|
|1|2|3|4|

私が望んでた結果は以下のような感じなのですが、何か良い方法はありますか?

|id(A_I)|foo|bar|baz|
|--------------|
|1|2|2|2|

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

SQL

1create table test(id int not null primary key auto_increment,foo int,bar int,baz int); 2insert into test values(NULL,1,1,1);

だとして、

SQL

1insert into test values(NULL, 0, 0, 0) on duplicate key update 2id=1,foo = foo + 1,bar = foo + 1,baz = bar + 1;

してもduplicate keyはないので新しいデータが追加されるだけですよ

SQL

1insert into test values(1, 0, 0, 0) on duplicate key update 2baz = bar + 1,bar = foo + 1,foo = foo + 1;

のようidを明示してinsertして、逆からいれてあげるだけじゃないですか?

追記

あまり推奨されていませんが変数経由で処理することも検討ください

SQL

1insert into test values(1, 0, 0, 0) on duplicate key update 2foo = (@a:=foo) + 1,bar = (@b:=bar)*0 + @a + 1,baz = @b + 1;

投稿2016/11/01 03:43

編集2016/11/01 08:25
yambejp

総合スコア114747

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

k725

2016/11/01 03:49

申し訳ないです。values(NULL, 0, 0, 0)ではなく、values(1, 0, 0, 0)でした。
yambejp

2016/11/01 03:53

で、回答したとおりfoo→bar→bazをbaz→bar→fooのように 逆からいれてやる件はいかがでしょうか?
yambejp

2016/11/01 08:25

変数経由の処理を追記しておきました
guest

0

これでは事足り無そうな感じですが。

sql

1insert into test (id) values(1) 2 ON DUPLICATE KEY UPDATE 3 foo = foo + 1, 4 bar = foo, 5 baz = bar;

こんな感じを拡張されてはいかがでしょうか?

sql

1insert into test select * from test s where s.id=1 2ON DUPLICATE KEY UPDATE 3 foo = test.foo + 1, 4 bar = s.foo, 5 baz = s.baz;

s.fooで更新前の値が入るのを利用する。

投稿2016/11/01 03:39

編集2016/11/01 04:49
A.Ichi

総合スコア4070

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

k725

2016/11/01 03:49 編集

実際には1を加算するのでは無く、CASE文でfooなどを比較する…というのをfoo, bar, bazの=以降でやっています。 ``` (略) foo = (CASE WHEN foo > bar THEN :hoge ELSE foo END), # ここは思った通り bar = (CASE WHEN foo > bar THEN :fuga ELSE bar END), # fooが:hogeに変わった場合意図したとおりに動かない baz = (CASE WHEN foo > bar THEN :piyo ELSE baz END); #〃 ``` 上記のような場合だと 条件自体が思っていたのと違ってしまうため困っています。
guest

0

sql

1 foo = foo + 1, 2 bar = foo + 1, 3 baz = bar + 1;

ではなく

sql

1 foo = foo + 1, 2 bar = bar + 1, 3 baz = baz + 1;

したらなりませんか?

idがPKでしょうか?
(NULL, 0, 0, 0)、1ではなくNULLですか?

###追記

sql

1INSERT INTO 2 test (id, foo, bar, baz) 3VALUES 4 (NULL, 0, 0, 0) 5ON DUPLICATE KEY UPDATE 6 id = 1, 7 foo = foo + 1, 8 bar = foo + 1, 9 baz = bar + 1;

まずこれではvalueのidにNULLを指定しているのでai設定されているならどんどん(NULL, 0, 0, 0)でinsertされるだけでON DUPLICATE KEY UPDATEに入ってこないと思うのですが。。。。

投稿2016/11/01 03:24

編集2016/11/01 03:37
hiim

総合スコア1689

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

k725

2016/11/01 03:26

実際のSQLクエリではもう少し複雑になっており、CASE文を使用しているので厳しいです。
hiim

2016/11/01 03:29

それではやらいたい事が少し見えてこないのですが、foo,bar,bazをインクリメントしたいという事ではないのですか?
k725

2016/11/01 03:29

>idがPKでしょうか? >(NULL, 0, 0, 0)、1ではなくNULLですか? 仰るとおりIDがプライマリキーになっています。(A_Iも有効にしているのでNULLで間違いないです)
k725

2016/11/01 03:34

>それではやらいたい事が少し見えてこないのですが、foo,bar,bazをインクリメントしたいという事ではないのですか? インクリメントしたいわけではありません。
k725

2016/11/01 03:40

失礼しました。確かにNULLではなく1ですね。 修正しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問