SQL文で登録されているデータを計算し、
計算したデータを同じテーブルに登録するような処理を自動で行うことは可能でしょうか。
1つ目 2つ目 3つ目 100 100 100 200 300 200 400 400 200
という様なテーブルがあったとしたら
1つ目 2つ目 3つ目 合計 100 100 100 300 200 300 200 700 400 400 200 1000
こんな感じで合計をだしたカラムを作りたいです。
追記--
合計のカラムには最初は値が入ってない想定です。(1つ目2つ目3つ目が変更されるのでそれに準じて合計の値も変更が自動でされる)
よろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

退会済みユーザー
2016/09/27 13:29

回答4件
0
MySQL5.7 をお使いでしたら、ジェネレーテッド・カラムを使うのが良さそうです。
https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_generated_column
A column whose value is derived on demand by computing a set of expressions or functions.
これを使用すると、
「1つ目2つ目3つ目が変更されるのでそれに準じて合計の値も変更が自動でされる」
を、実現できます。
以下の例ではcol_sum
がジェネレーテッド・カラムで、col_1 + col_2 + col_3
の結果を表現しています。
sql
1mysql> CREATE TABLE tbl ( 2 -> col_1 int, 3 -> col_2 int, 4 -> col_3 int, 5 -> col_sum int AS (col_1 + col_2 + col_3) 6 -> ); 7Query OK, 0 rows affected (0.10 sec) 8 9mysql> INSERT INTO tbl (col_1, col_2, col_3) VALUES 10 -> (100, 100, 100), 11 -> (200, 300, 200), 12 -> (400, 400, 200); 13Query OK, 3 rows affected (0.00 sec) 14Records: 3 Duplicates: 0 Warnings: 0 15 16mysql> SELECT * FROM tbl; 17+-------+-------+-------+---------+ 18| col_1 | col_2 | col_3 | col_sum | 19+-------+-------+-------+---------+ 20| 100 | 100 | 100 | 300 | 21| 200 | 300 | 200 | 700 | 22| 400 | 400 | 200 | 1000 | 23+-------+-------+-------+---------+ 243 rows in set (0.00 sec) 25 26mysql> UPDATE tbl SET col_3 = col_3 * 2; 27Query OK, 3 rows affected (0.00 sec) 28Rows matched: 3 Changed: 3 Warnings: 0 29 30mysql> SELECT * FROM tbl; 31+-------+-------+-------+---------+ 32| col_1 | col_2 | col_3 | col_sum | 33+-------+-------+-------+---------+ 34| 100 | 100 | 200 | 400 | 35| 200 | 300 | 400 | 900 | 36| 400 | 400 | 400 | 1200 | 37+-------+-------+-------+---------+ 383 rows in set (0.00 sec)
MySQL5.6 以前をお使いであれば、トリガーを使用すれば同様のことが実現できます。
https://dev.mysql.com/doc/refman/5.6/ja/create-trigger.html
トリガーとは、テーブルに関連付けられ、そのテーブルに対して特定のイベントが発生するとアクティブ化される名前付きデータベースオブジェクトのことです。
対象のテーブルに対して INSERT および UPDATE が実行された際にcol_sum
の値を再計算するトリガーを作成すればよいです。
sql
1mysql> CREATE TABLE tbl_2 ( 2 -> col_1 int, 3 -> col_2 int, 4 -> col_3 int, 5 -> col_sum int 6 -> ); 7Query OK, 0 rows affected (0.02 sec) 8 9mysql> CREATE TRIGGER ins_sum BEFORE INSERT ON tbl_2 FOR EACH ROW SET NEW.col_sum = NEW.col_1 + NEW.col_2 + NEW.col_3; 10Query OK, 0 rows affected (0.01 sec) 11 12mysql> CREATE TRIGGER upd_sum BEFORE UPDATE ON tbl_2 FOR EACH ROW SET NEW.col_sum = NEW.col_1 + NEW.col_2 + NEW.col_3; 13Query OK, 0 rows affected (0.00 sec) 14 15mysql> INSERT INTO tbl_2 (col_1, col_2, col_3) VALUES 16 -> (100, 100, 100), 17 -> (200, 300, 200), 18 -> (400, 400, 200); 19Query OK, 3 rows affected (0.00 sec) 20Records: 3 Duplicates: 0 Warnings: 0 21 22mysql> SELECT * FROM tbl_2; 23+-------+-------+-------+---------+ 24| col_1 | col_2 | col_3 | col_sum | 25+-------+-------+-------+---------+ 26| 100 | 100 | 100 | 300 | 27| 200 | 300 | 200 | 700 | 28| 400 | 400 | 200 | 1000 | 29+-------+-------+-------+---------+ 303 rows in set (0.00 sec) 31 32mysql> UPDATE tbl_2 SET col_3 = col_3 * 2; 33Query OK, 3 rows affected (0.01 sec) 34Rows matched: 3 Changed: 3 Warnings: 0 35 36mysql> SELECT * FROM tbl_2; 37+-------+-------+-------+---------+ 38| col_1 | col_2 | col_3 | col_sum | 39+-------+-------+-------+---------+ 40| 100 | 100 | 200 | 400 | 41| 200 | 300 | 400 | 900 | 42| 400 | 400 | 400 | 1200 | 43+-------+-------+-------+---------+ 443 rows in set (0.00 sec)
追記
MySQLでは、col_1, col_2, col_3
のいずれかが NULL の場合、
col_1 + col_2 + col_3 = NULL
となります。
https://dev.mysql.com/doc/refman/5.6/ja/problems-with-null.html
NULL を含む式は、式に関連する演算子および関数のドキュメントに示されている場合を除き、常に NULL 値を生成します。
"合計をだしたカラム"に NULL が格納されるのを避けたい場合、
yambejp様のコメントにある通り、col_1, col_2, col_3
に NOT NULL 制約をつけるか、
NULL を適切な値に変換した上で合計を計算するなどの対処をしてください。
投稿2016/09/28 03:41
編集2016/09/28 06:17総合スコア4791
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/09/28 04:31

0
あえて自動登録する、という主題から観点を外した回答をしてみます。
もしも見せ方としてそ合計列が欲しいだけで実テーブルへのこだわりがないとしたら、
一般的なDBMSが漏れなくサポートしてるであろうビュー機能を用いるという解決策もあると思います。
(Oracle、SQL Sever、MySQLなどいずれもサポートされており、標準SQLの範囲なのでベンダ依存もほとんどありません。)
MySQLでビューを用いるなら下記のような感じで定義します。
SQL
1CREATE OR REPLACE VIEW sample_view AS 2SELECT 3 col1 4, col2 5, col3 6, col1 + col2 + col3 AS total 7FROM 8 sample_table
利用するときはビュー名で下記のようにアクセスします。
SQL
1SELECT 2 col1 3, col2 4, col3 5, total 6FROM 7 sample_view
ビューのメリットとしては、
実体を持たないという特徴があるため、
実テーブル側の値やデータ数が変わった場合も、自動計算して出力してくれる点です。
ただしデメリットもまた実体を持たないことで、
内部的にはビューで定義したSELECT句が起動されるだけなので、
下手な使い方をするとパフォーマンス的に不利となります。
ちなみにビューを経由したINSERTやUPDATEなどには色々と制約があるので、
その際は素直に実テーブルに対して行うと良いでしょう。
SQL
1INSERT INTO sample_table (col1, col2, col3) VALUES (100, 500, 400)
尚ビューを用いる場合も例に漏れず、
KiyoshiMotokiさんの回答にあるようなNULL演算の問題が起こり得ます。
これはMySQLに限った話ではなく、
一般的DBMSは全てこのような挙動を取ります。
参考までにNULLの話題を扱ったQAもありますので、
興味があるようでしたら一読して下さい。
対策方法としては、
実テーブル側にカラムにNOT NULL制約をかけるか、
SELECTする際にベンダ拡張のIFNULL関数か標準SQL関数のCOALESCE関数を利用してNULLをエスケープするかしておきましょう。
投稿2016/09/28 10:15
編集2016/09/28 10:29総合スコア1636
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
追記
自動で
という前提を忘れていたので、下記は忘れてください。
合計のカラムは最初からあるという前提ですよね。
単純に全レコードをそれぞれけいさんするのであれば次のようになります。
(1つ目:n1、2つ目:n2、3つ目:n3、合計:total、とする)
SQL
1update tbl set total=n1+n2+n3
特定のレコードのみなど条件を付けたいのであれば、WHERE句を指定することもできます。
SQL
1update tbl set total=n1+n2+n3 where 条件...
投稿2016/09/28 00:13
編集2016/09/28 07:20総合スコア17000
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
Oracle12.1.0EE 64bit for Windows
CREATE TABLE TAB1
(
NUM1 NUMBER(5)
, NUM2 NUMBER(5)
, NUM3 NUMBER(5)
) ;
INSERT INTO TAB1(NUM1, NUM2, NUM3) VALUES(100, 100, 100) ;
INSERT INTO TAB1(NUM1, NUM2, NUM3) VALUES(200, 300, 200) ;
INSERT INTO TAB1(NUM1, NUM2, NUM3) VALUES(400, 400, 200) ;
COMMIT ;
-- と、ここまでが準備
-- 合計を取得する時に計算するので合計は通常列では持ちません。
COLUMN NUM1 HEADING "1つ目"
COLUMN NUM2 HEADING "2つ目"
COLUMN NUM3 HEADING "3つ目"
COLUMN GOKEI HEADING "合計"
SELECT T1.NUM1
, T1.NUM2
, T1.NUM3
, T1.NUM1 + T1.NUM2 + T1.NUM3 AS GOKEI
FROM TAB1 T1 ;
1つ目 2つ目 3つ目 合計
100 100 100 300 200 300 200 700 400 400 200 1000
投稿2016/09/27 12:04
総合スコア16417
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。