DBからTABLEAを読み込んでおいて、そのデータを違うテーブルに格納したい(常にデータをIDごとに最新の1件としたい)と思い、
以下URLを参考にやってみたのですが、うまく動いてくれません。
http://naruhodo.television.co.jp/qa4380807.html?check_ok=1
プログラムについてご教授願ください。
[MYSQL5.1 PHP5.2]
// 接続
require_once("conn.php");
// SQL
$result = mysql_query("SELECT id, name, sum(price) AS price FROM TABLEA GROUP BY id");
// 変数格納&DB書き換え
while ($row = mysql_fetch_array($result)) {
$ins_sql[] = "UPDATE TABLEA SET
id = '".$row[id]."',
name = '".$row[name]."',
price = '".$row[price]."'";
}
for ($i=0; $i < count($ins_sql); $i++){
$res = mysql_query($ins_sql[$i]);
標準的SQLであれば、面倒なのだがテーブルBに既存のid=1にはUPDATE、テーブルBに存在しないid=2にはINSERTで対処するという二段階になる。
だがMySQLにはINSERTとUPDATEの両方を併せ持つようなREPLACEというものが用意されておるから1発だ。
まずは、テーブルAからid毎の最新の一件を抽出する事を考える。これは以前のものの再利用だ。以前よりシンプルですむぞ。
SET @id = '', @c = 0; SELECT id, date, price FROM ( SELECT * , IF(@id <> id, @c := 1, @c := @c + 1) c , IF(@id <> id, @id := id, @id := @id) i FROM テーブルA ORDER BY id, date DESC ) a WHERE c = 1;
最新を抜き出せる事が確認できたなら本番だ。上記に1行加えるだけだ。
SET @id = '', @c = 0; REPLACE INTO テーブルB SELECT id, date, price FROM ( SELECT * , IF(@id <> id, @c := 1, @c := @c + 1) c , IF(@id <> id, @id := id, @id := @id) i FROM テーブルA ORDER BY id, date DESC ) a WHERE c = 1;
http://dev.mysql.com/doc/refman/5.1/ja/replace.html
REPLACEを使う場合に注意せねばならぬのはPRIMARY KEYだ。以下の状態を想定しておる。
CREATE TEMPORARY TABLE テーブルB(id INT, date INT, price INT, PRIMARY KEY(id));
id毎に最新の1件しか入れぬのだからキーはidだけで十分という事だ。
テーブルAのPRIMARY KEYは今回は問題とはならぬが、処理速度面からインデックスはついているほうがいいだろう。
基本的に 何がうまく行かないのか書いてもらったほうがいい。
ここで なんとかというエラーが出るとか・・・。
で質問のプログラムを見ると 違うテーブルに格納すると言いながら
>UPDATE TABLEA SET
となっています。
これでは TABLEA に格納されてしまうことになりますので、最低限 テーブル名を別のものに
したほうがいいでしょう。
http://dev.mysql.com/doc/refman/4.1/ja/update.html
UPDATE [LOW_PRIORITY] [IGNORE] tbl_name
SET col_name1=expr1 [, col_name2=expr2 ...]
[WHERE where_definition]
[ORDER BY ...]
[LIMIT row_count]
>ここで なんとかというエラーが出るとか
phpを実行するとエラーは出ませんが、データがDBへ格納されていない状態です。
>これでは TABLEA に格納されてしまうことになります
申し訳ないですが、これも記載ミスです。
・・・AS price FROM TABLEB GROUP BY id
が正解でした。
>phpを実行するとエラーは出ませんが、データがDBへ格納されていない状態です
明示的にcommitを発行してみては?
あと、UPDATEはすでにレコードがない場合は更新されません。
今回の場合はINSERT文を使うのでは?
>明示的にcommitを発行してみては?
ごめんなさい、当方初心者なもので意味が解りません。
>今回の場合はINSERT文を使うのでは?
INSERT文でも上書きできますかね?
// 接続 require_once("conn.php"); // SQL $result = mysql_query("SELECT id, name, sum(price) AS price FROM TABLEB GROUP BY id"); // 変数格納&DB書き換え while ($row = mysql_fetch_array($result)) { $rs = mysql_query("SELECT COUNT(*) FROM TABLEA WHERE id = '".$row[id]."'"); $cnt = 0; while ($row = mysql_fetch_array($rs)) { $cnt++; } if ($cnt) { $res = mysql_query("UPDATE TABLEA SET id = '".$row[id]."',name = '".$row[name]."',price = '".$row[price]."'"); } else { $res = mysql_query("INSERT INTO TABLEA (id,name,price) VALUES ('".$row[id]."','".$row[name]."','".$row[price]."')"); } }
回答ありがとうございます。
書き方等大変参考になりました。
同じような質問が出ていましたね。
参考になりました。
標準的SQLであれば、面倒なのだがテーブルBに既存のid=1にはUPDATE、テーブルBに存在しないid=2にはINSERTで対処するという二段階になる。
だがMySQLにはINSERTとUPDATEの両方を併せ持つようなREPLACEというものが用意されておるから1発だ。
まずは、テーブルAからid毎の最新の一件を抽出する事を考える。これは以前のものの再利用だ。以前よりシンプルですむぞ。
SET @id = '', @c = 0; SELECT id, date, price FROM ( SELECT * , IF(@id <> id, @c := 1, @c := @c + 1) c , IF(@id <> id, @id := id, @id := @id) i FROM テーブルA ORDER BY id, date DESC ) a WHERE c = 1;
最新を抜き出せる事が確認できたなら本番だ。上記に1行加えるだけだ。
SET @id = '', @c = 0; REPLACE INTO テーブルB SELECT id, date, price FROM ( SELECT * , IF(@id <> id, @c := 1, @c := @c + 1) c , IF(@id <> id, @id := id, @id := @id) i FROM テーブルA ORDER BY id, date DESC ) a WHERE c = 1;
http://dev.mysql.com/doc/refman/5.1/ja/replace.html
REPLACEを使う場合に注意せねばならぬのはPRIMARY KEYだ。以下の状態を想定しておる。
CREATE TEMPORARY TABLE テーブルB(id INT, date INT, price INT, PRIMARY KEY(id));
id毎に最新の1件しか入れぬのだからキーはidだけで十分という事だ。
テーブルAのPRIMARY KEYは今回は問題とはならぬが、処理速度面からインデックスはついているほうがいいだろう。
回答有難うございます。
素晴らしいです。結果、パーフェクトでした。
UPDATEも、新規IDに対してのINSERTもできていました。
REPLACE構文はわたしの教科書には無いものでしたので、とても勉強になりました。
回答有難うございます。
素晴らしいです。結果、パーフェクトでした。
UPDATEも、新規IDに対してのINSERTもできていました。
REPLACE構文はわたしの教科書には無いものでしたので、とても勉強になりました。