あいさつ
むかし業務で必要になったSQLの小技?を紹介しようと思います。(初投稿です)
本題
サンプルケース
- table1
id | name | hoge |
---|---|---|
1 | taro | 3 |
2 | john | 6 |
3 | kevin | 10 |
4 | saya | 1 |
- table2
id | piyo | grade |
---|---|---|
1 | 5 | 2 |
2 | 9 | 3 |
3 | 8 | 5 |
4 | 7 | 2 |
以上のような二つのテーブルがあり、なんらかの事情でgradeが2の人のみ、table1のhogeの値をtable2のpiyoの値と一致するよう更新する必要が出たとしましょう。
この作業を一括で行いたいときどうしたらよいでしょう。
update
(SELECT a.hoge hoge,
b.piyo piyo,
b.grade grade
FROM table1 a
INNER JOIN table2 b
ON a.id = b.id) SET hoge = piyo
WHERE grade = 2;
上記SQL実行後table1は以下のようになります。
id | name | hoge |
---|---|---|
1 | taro | 5 |
2 | john | 6 |
3 | kevin | 10 |
4 | saya | 7 |
結合したときgradeが2だったtaroとsayaの2レコードのhoge値が、table2のpiyo値で更新されます。
ポイントは結合しているサブクエリ内のselect句で各カラムに別名をつけていることです。
なぜならサブクエリの外側で必要になるからです。
ちなみに別名の付け方を見ればお気づきと思いますが、これはoracleでの書き方です。
oracleではupdate句の中でjoinが使えません。(できるバージョンもあるかもしれません、、)
SQL serverの場合は
UPDATE table1 SET a.hoge = b.piyo
FROM table1 AS a
INNER JOIN table2 AS b
ON a.id = b.id
WHERE b.grade = 2;
こんな感じで割と素直に書けるようです。
postgresだと、また違った書き方だったような気がするのですが、ぱっと出てこないので割愛します。
余談&思い出話
こういった作業が必要になったのが1年以上昔のはなしなので、実際どういう場面だったか正確には覚えていないのですが、軽いネタにはちょうどいいかと初投稿してみました。
当時はVB.NETとoracleを使った市役所向けパッケージをやっていて、レガシーな環境にうんざりしていましたね。
とはいえこのような学びはちょこちょこあったのですが。わたしは最近SQLを直接書く機会があまりないですね。
ちなみにサンプルケースのテーブルがクソってのは置いといてください。
このようなSQLが必要になる場面はテーブル設計がちゃんとしていればあまりなさそうですよね。
SQLを見てしまえば「なんだ単純じゃないか」という話ですが、どうしたらいいかちょっと悩んだ記憶があるので記事にしました。
それでは。