SQL文での効率的な処理方法とは?

このQ&Aのポイント
  • PHPでSQL文を効率的に作成する方法についての質問です。質問者は、複数の$_REQUESTの値をMYSQLのSQL文に組み込んで処理したいと考えています。具体的には、$lllという配列に$_REQUESTのキーとMYSQLのカラム名を対応させて、foreachとswitch文で処理を分けながら$qqqというSQL文に組み込んでいます。また、キーごとに処理を分けるための条件分岐も記述しています。
  • 質問者のコードでは、$_REQUESTの各値をキーごとに$lllと対応させて、処理を分けながら$qqqのSQL文に組み込んでいます。具体的には、GETパラメータ「getA」の場合は配列に分割し、getBの場合はそのまま、getCの場合はそのままの値を使用しています。また、WHERE句の条件もキーごとに分岐して記述しています。
  • 以上の処理で、質問者は$_REQUESTの値を効率的にMYSQLのSQL文に組み込めていると考えています。なお、$qqqのSQL文では、指定された条件でテーブルのデータを取得し、指定の並び順で結果を返すようになっています。また、取得するデータの数にも制限をかけています。
回答を見る
  • ベストアンサー

いろいろな処理をさせてSQL文を効率的に作りたい

$_REQUEST['getA']、$_REQUEST['getB']、$_REQUEST['getC'] ・・・ とあり、 これらをMYSQLのSQL文に効率的に組み込んでいきたいです。 mysqlのデータと$_REQUESTのキー名と対応させた$lllを foreachでそれぞれをswitchで処理を分けて、 $qqqのSQL文に組み込んでいるつもりです。 よろしくお願いします。 $lll = array( "getA"=>"mysql_colum_name_A", "getB"=>"mysql_colum_name_B", "getC"=>"mysql_colum_name_C", "getD"=>"mysql_colum_name_D", "getE"=>"mysql_colum_name_E" ); foreach($lll as $key=>$val){ if(!isset($_REQUEST[$key]) or $_REQUEST[$key]==='') continue; switch($key){ case "getA": $ga = explode("+", $_REQUEST[$key]); $val_A = $val; break; case "getB": $gb = $_REQUEST[$key]; $val_B = $val; break; case "getC": $gc = $_REQUEST[$key]; $val_C = $val; break; case "getD": $gd = $_REQUEST[$key]; $val_D = $val; break; ~ 他のcaseが続く ~ } } $qqq =<<<__SSS__ SELECT * FROM table WHERE 1 AND ga0 <= val_A AND val_A < ga1 AND `colum_B` BETWEEN CURDATE() - INTERVAL gb YEAR AND CURDATE() - INTERVAL 1 DAY AND gc <= val_C AND gd <= val_D AND val_E IN(ge) ORDER BY field deskORasc LIMIT L1,L2; __SSS__; $sss = $ddd->prepare($qqq); $sss->execute(array( ':ga0'=>$ga[0], ':ga1'=>$ga[1], ':val_A'=>$val_A, ':gb'=>$gb, ':val_B'=>$val_B, ':gc'=>$gc, ':val_C'=>$val_C, ':gd'=>$gd, ':val_D'=>$val_D, ':ge'=>$ge, ':val_E'=>$val_E, ~いろいろなものが続く~ ':field'=>$field, ':deskORasc'=>$deskORasc, ':L1'=>0, ':L2'=>50 )); $rrr = $sss->fetchAll(PDO::FETCH_ASSOC);

  • PHP
  • 回答数1
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • shimix
  • ベストアンサー率54% (865/1590)
回答No.1

質問は何でしょうか? ざっと見たところでは、 (1) $_RESUEST[$key]が空文字列だったら処理をスキップしているのにそれを考慮してステートメントを組み立てていない (2) プレースホルダの記述がおかしい(プレースホルダになっていない)。 という点が気にはなりますが、いずれにしても$qqqやそれに引き渡す値をprintしてみればわかることだとは思います(それがデバッグですから)。

taurin1000kg
質問者

お礼

$_REQUEST[$key]があるだけ、それに合わせた処理をさせて、 必要なだけSQL文を組み立てていきたいです。 指摘してもらった(1)と(2)はこちらでオッケーですか? $lll = array( "getA"=>"mysql_colum_name_A", "getB"=>"mysql_colum_name_B", "getC"=>"mysql_colum_name_C", "getD"=>"mysql_colum_name_D", "getE"=>"mysql_colum_name_E" ); $yyy = 'SELECT * FROM table WHERE 1'; foreach($lll as $key=>$val){ if(!isset($_REQUEST[$key]) or $_REQUEST[$key]==='') {$_REQUEST[$key]="";} switch($key){ case "getA": $ga = explode("+", $_REQUEST[$key]); $yyy .= ' AND {$r[0]} <= {$val} AND {$val} < {$r[1]}'; break; case "getB": $yyy .= 'AND {$val} BETWEEN CURDATE() - INTERVAL {$_REQUEST[$key]} YEAR AND CURDATE() - INTERVAL 1 DAY'; break; case "getC": case "getD": case "getE": $yyy .= ' AND {$_REQUEST[$key]} <= {$val}'; break; ~ 他のcaseが続く ~ } } $ddd = new PDO($host,$user,$pass); $sss = $ddd->prepare($qqq); $rrr = $sss->fetchAll(PDO::FETCH_ASSOC);

関連するQ&A

  • GETで送られたデータを元に必要なSQL文を作る

    FORMのSELECTなどで選択されたデータをGETで送り、 それをもとにSQLの文章を作りたいと思っています。 $yyy = "SELECT * FROM table WHERE 1 AND {$a} < mysqlA AND {$b} < mysqlB AND mysqlC IN({$b}) ・・・"; のようにすればSQLの文章を作れると思いますが、FORMで選択されていないデータを対象にした文章までも入ってしまいます。 FORMより送られたデータだけのSQLの文章を作りたいです。 下記のようなやり方以外に良い方法はありますか? MYSQLのデータ ------------------------------- mysqlA | mysqlB |  ・・・ 4     |  55  |  ・・・ 5     |  33  |  ・・・ 77    |  17  |  ・・・ :       :     : :       :     : <?php  :  : $lll = array( "getA"=>"mysqlA", "getB"=>"mysqlB", "getC"=>"mysqlC", "getD"=>"mysqlD", "getE"=>"mysqlE",   : ); $yyy = 'SELECT * FROM table WHERE 1'; foreach($lll as $key=>$val){ if(!isset($_REQUEST[$key]) or $_REQUEST[$key]==='') {$_REQUEST[$key]="";} switch($key){ case "getA": $ga = explode("+", $_REQUEST[$key]); $yyy .= ' AND {$ga[0]} <= {$val} AND {$val} < {$ga[1]}'; break; case "getB": $yyy .= 'AND {$val} BETWEEN CURDATE() - INTERVAL {$_REQUEST[$key]} YEAR AND CURDATE() - INTERVAL 1 DAY'; break; case "getC": case "getD": case "getE": $yyy .= ' AND {$_REQUEST[$key]} <= {$val}'; break; ~ 他のcaseが続く ~ } } $ddd = new PDO($host,$user,$pass); $sss = $ddd->prepare($qqq); $rrr = $sss->fetchAll(PDO::FETCH_ASSOC);  :  : ?> <html xml:lang="ja" lang="ja"> <head> <title></title> </head> <body> <form action="#">   : <select name="getB" onchange="changeDate()"> <option value="0"<?php if(isset($_REQUEST[$getB]) && $_REQUEST[$getB]==0){echo ' selected="selected"';} ?>>0</option> <option value="20"<?php if(isset($_REQUEST[$getB]) && $_REQUEST[$getB]==20){echo ' selected="selected"';} ?>>20</option> <option value="50"<?php if(isset($_REQUEST[$getB]) && $_REQUEST[$getB]==50){echo ' selected="selected"';} ?>>50</option> </select>   :   :

    • 締切済み
    • PHP
  • SQL文の実行結果を変数で受けて、それを連想配列に格納したいです。

    SQL文の実行結果を変数で受けて、それを連想配列に格納したいです。 (カラム名を連想配列のキーにします。) また、値をHTMLエスケープ処理したいと考えています。 下記のソースを書いてみましたが、配列$all[]にうまく入りません。 $qresult = mysql_query($qstring); $all = array(); while (list ($key, $val) = mysql_fetch_assoc($qresult)){  $all[$key] = htmlentities($val, ENT_QUOTES,EUCJP); } また、3行目をeach(mysql_fetch_assoc($qresult))に変更してもみましたが、 「Variable passed to each() is not an array or object」エラーが出ます。 mysql_fetch_assocの戻り値は連想配列では無いのでしょうか。 $qresult = mysql_query($qstring); $all = array(); while ($rec = mysql_fetch_assoc($result)){  $all[] = $rec; } 上記だと問題なく取得出来るのですが。。。 何が悪いのでしょうか。

    • ベストアンサー
    • PHP
  • mysql_fetch_arrayを何度も使いたい

    phpとmysqlを使っています。 配列$valuesがあります。 その値は一部だけmysqlのフィールドdの中に格納しています。 両方の値を比較してもし一致すればチェックボックスを作るという処理をしています。 また、同時に一致した数もそれぞれ取得したいと考えています。 イメージ的には、□はチェックボックスとして()には、その配列の値とフィールドdの値に一致する数が入ります。 □(33) □(13) □(1) □(22) □(3)  □(16) □(15) □(9) □(23) □(32)  □(4) □(16) □(7) □(6) □(11)  □(5) □(21) □(1) □(4) □(15)  □(13) □(10) □(3) □(19) □(8)  □(0)のとき非表示になるようにしています。 <?php $m = mysql_connect('localhost','root',password); $mm = "SELECT * FROM tableA"; mysql_set_charset('utf8'); $mmm = mysql_query($mm,$m); $values=array( "chk1"=>array("a1","a2","a3","a4","a5","a6","a7","a8","a9","a10") ,"chk2"=>array("b1","b2","b3","b4","b5","b6","b7","b8","b9","b10") ,"chk3"=>array("c1","c2","c3","c4","c5","c6","c7","c8","c9","c10") ); foreach($values as $key=>$array){ foreach($array as $val){ $checked=(isset($_REQUEST[$key]) and in_array($val,$_REQUEST[$key]))?" checked":""; $count = ""; while($r = mysql_fetch_array($mmm)){ if($val === $r['d']){$count++:} } if($count>0 && !$count==""){ $h = $h.htmlspecialchars($val, ENT_QUOTES, 'UTF-8').'<input type="checkbox" name="'.$key.'[]" value="'.$val.'"'.$checked.'/>('.$count.') '."\n"; } } } print "<br />\n"; } ?> <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> </head> <body> <form method="get" action="checkbox2.php"> <?php echo $h; ?> <input type="submit" value="送信" /> </form> </body> </html> これではmysql_fetch_arrayが一度しか使えないので、配列の値a2以降が進みません。 こういうときはどのようにするべきでしょうか。 また、if($val === $r['d']){$count++:}でカウントしていますが、もっといい方法はありますか。 その他変な箇所があれば指摘して頂けると嬉しいです。 お願いします。

    • ベストアンサー
    • PHP
  • foreachの表示に追加するには

    http://okwave.jp/qa2460708.html と同じようなテーブル構造で、同じようなhtmlへの書き出しを行っています。 No.1さんの回答の下記のスクリプトを参考にし、うまく表示することができました。 $sql="SELECT `ID`,`SHOPNAME` FROM `SHOP`"; $res = mysql_query($sql,$link); while ($rows = mysql_fetch_assoc($res)) { $SHOP[$rows["ID"]]=$rows["SHOPNAME"]; } $sql="SELECT `ID`,`ITEMNAME` FROM `ITEM`"; $res = mysql_query($sql,$link); while ($rows = mysql_fetch_assoc($res)) { $ITEM[$rows["ID"]]=$rows["ITEMNAME"]; } foreach($SHOP as $key1=>$val1){ foreach($ITEM as $key2=>$val2){ $LINK[$key1][$key2]="&nbsp;"; } } $sql="SELECT `SHOP`,`ITEM` FROM `LINK`"; $res = mysql_query($sql,$link); while ($rows = mysql_fetch_assoc($res)) { $LINK[$rows["SHOP"]][$rows["ITEM"]]="○"; } print<<<eof <table border> <thead> <tr> <th>&nbsp;</th> eof; foreach($ITEM as $key2=>$val2){ print "<th>$val2</th>"; } print<<<eof </tr> </thead> <tbody> eof; foreach($SHOP as $key1=>$val1){ print "<tr>"; print "<td>$val1</td>"; foreach($ITEM as $key2=>$val2){ print "<td>{$LINK[$key1][$key2]}</td>"; } print "</tr>"; } print<<<eof </tbody> </table> eof; しかし、下記のテーブルに項目が1つ追加され、それも表示できるようにして欲しいと依頼されました。 Table:SHOP ID  SHOPNAME STATION ------------------------ 1   東京 | 表参道 2   大阪 | 梅田 3   福岡 | 天神 (略) 結果としては下記のように表示したいです。 NAME |STATION|化粧品|家具 |園芸 |食品 |家電 | ------------------------------------------------ 東京 | 表参道|   |   |   | ○ |   | 大阪 | 梅田 |   |   |   |   | ○ | 福岡 | 天神 | ○ | ○ |   |   |   | (略) 配列をよく理解できていないため、スクリプトをそのまま真似して $STATION[$rows["ID"]]=$rows["STATION"]; を作ったり $SHOP[$rows["ID"]][$rows["STATION"]]=$rows["SHOPNAME"]; を作ったりして無理矢理展開してみようとしましたが やはり表がぐちゃぐちゃになってしまいます。 どうすればうまく表示できるか、アドバイス頂けませんでしょうか。

    • ベストアンサー
    • PHP
  • テーブルデータ表示

    mysqlからデータをphpで取得し以下のような多次元配列になっています。 Array ( [0] => Array ( [id] => 116 [name] => あああ ) [1] => Array ( [id] => 58 [name] => いいい ) [2] => Array ( [id] => 89 [name] => ううう ) ) 単純にデータを表示させたく以下のようにしましたが<th>$key2</th>の箇所が上記配列の場合 2回繰り返されて表示されてしまいます。ここはフィールド名なので1回の表示でいいのですが どのように記述すれば思うような表示になるでしょうか? echo "<table border=\"1\">"; echo "<tr>"; foreach ($tmp1 as $key => $val) { foreach ($val as $key2 => $val2) { echo "<th>" . $key2 . "</th>"; //フィールド名 } } echo "</tr>"; foreach ($tmp1 as $key => $val) { echo "<tr>"; foreach ($val as $key2 => $val2) { echo "<td>" . $val2 . "</td>"; // 取得したデータをある分だけ繰り返し } echo "</tr>"; } echo "</table>";

    • ベストアンサー
    • PHP
  • レコードなしは挿入、レコードありは更新する方法

    該当レコードなしのときは挿入、該当レコードがあるときは更新する方法を教えてください データベース初心者です 該当レコードなしのときは挿入(INSERT)、該当レコードがあるときは更新(UPDATE)する方法を教えてください。 MySQL 5.0.67 レコードは下記のようになります。 desc table; +----------+----------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+----------------------+------+-----+---------+-------+ | val1 | smallint(6) | NO | PRI | 0 | | | val2 | smallint(6) | NO | PRI | 0 | | | val3 | smallint(6) | NO | PRI | 0 | | | date_y | char(4) | NO | PRI | | | | date_m | char(2) | NO | PRI | | | | pre | bigint(19) | NO | | 0 | | | now | bigint(19) | NO | | 0 | | +----------+----------------------+------+-----+---------+-------+ 下記のSQL文で更新を行いました。 UPDATE table as c, ( SELECT val1, val2, val3, now FROM table WHERE date_y='2010' and date_m='10' ) as n SET c.pre=n.now, c.now=n.now WHERE c.val1=n.val1 and c.val2=n.val2 and c.val3=n.val3 and c.date_y='2010' and c.date_m='11'; このSQL文をINSERT~ON DUPLICATE KEY UPDATEにした場合、どのようなSQL文になるのかをご教授頂ければ幸いです。 一応、下記URLを参照したのだけど、うまくSQL文が書けませんでした。 12.2.4.3. INSERT ... ON DUPLICATE KEY UPDATE 構文 http://dev.mysql.com/doc/refman/5.1/ja/insert-on-duplicate.html 以上、宜しくお願い致します。

  • MySQLを反映させたプルダウンメニューについて

    『MySQLデータベースのテーブル』 ID、品名、色(1)、色(2)、色(3)、… (例:1、”靴下”、”白”、”赤”) 『PHP文』 <?php … $result = "select * from テーブル名 where name= \"靴下\""; print "<form method = POST action=「出力先」>"; print "<select name=color>"; $data = mysql_fetch_row($result); foreach($data as $key => $val){ if ($key>1 and $val !=null){ echo "<option value = '".$key."'>".$val."</option>"; } } …以下… ?>) 「ユーザーに品名をまずは選んでもらい、次にその品の色を選んでもらう」 というプログラムを組みたくて… ただし、品により色が多かったり少なかったりするため、 MYSQLから対応する色名を引き出してきてプルダウンに反映させる というような上記の方法をとりました。 ここで問題が発生… 次のページに選んでもらった色名のキー($key)が$_POST["color"]では受け取れていないのです。 form、select、input文、などを確かめましたが、ここに誤りはないようです。 プルダウンメニューが表示され、ページも飛ぶのですが、単純にPOST引き渡しができていないようなのです。 非常に困っております(泣) どなたかお詳しい方がいらっしゃいましたら、アドバイスをいただけませんでしょうか。 宜しくお願いします。

    • ベストアンサー
    • PHP
  • array値を別のテーブルへインサートしたい。

    phpとmysqlを見よう見まねでやっている 初心者です。 atableのチェックボックスよりPOSTした $sample_array(atable.indexの値が複数です。) をbtableへ移動したいと思い、以下の式を自分なりに 考えてみましたが上手くbtableへinsert されません。 atableの複数のindexは選ばれているようですが それをどうしたらbtableへ複数insertできるのか良くわかりません。 何が間違っているのか、atableからbtableへ複数insertできる式を 具体的に書いて頂くと大変助かります。 どうかご教授の程よろしくお願い致します。 $sample_array = $_POST['sample_array']; $where=""; if (isset($sample_array) and is_array($sample_array)) { $where .=" AND atable.index in ("; foreach ($sample_array as $key=>$val) { if($key>0) $where .=","; $where .="'" .mysql_real_escape_string($val) . "'"; } $where .=")"; } $sql= "select * from atable"; $sql .= " where 1"; $sql .= $where; $result = mysql_query( $sql ); while ( $row = mysql_fetch_array( $result ) ) { $sql = "insert into btable (a_no,b_no,c_no) values ('" . $row['no_a'] . "', '" . $row['no_b'] . "','" . $row['no_c'] . "')"; }

    • ベストアンサー
    • PHP
  • Mysqlとphpでソートや更新時の効率的な処理

    カラムの作成日時と更新日時のそれぞれでソート、 作成日時当日はNEWの文字を入れる。というものを作りたいと思っています。 <?php $cer = "SELECT * FROM data_data WHERE 1"; function orderbyset($cul, $sc, &$cer){ $cer .= " ORDER BY ".$cul." ".$sc; } if(isset($_GET['orderby'])){ switch($_GET['orderby']){ case 'md_asc': orderbyset('modified_date','ASC',$cer); break; case 'md_desc': orderbyset('modified_date','DESC',$cer); break; case 'cd_asc': orderbyset('create_data','ASC',$cer); break; case 'cd_desc': orderbyset('create_data','DESC',$cer); break; } } $acc = mysql_connect(ホスト,ユーザー,パスワード); $que = mysql_query($cer,$acc); $html = ""; while($row = mysql_fetch_array($que)){ $id = $row["id"]; $name = $row["name"]; $modified_date = $row["modified_date"]; $create_data = $row["create_data"]; $daydiff = floor((strtotime($modified_date)-strtotime($create_data))/(3600*24)); if($daydiff==0){$datatext = 'new';}else{$datatext='';} $html .= "<tr><td>$id</td><td>$name</td><td>$modified_date</td><td>$create_data</td><td>$datatext</td></tr>\n"; } ?> <html lang="ja"> <head> <title></title> </head> <body> <p>更新日時順<br /> <a href="data-sort.php?orderby=md_asc">昇順</a> <a href="data-sort.php?orderby=md_desc">降順</a> </p> <p>作成日時順<br /> <a href="data-sort.php?orderby=cd_asc">昇順</a> <a href="data-sort.php?orderby=cd_desc">降順</a> </p> <table><?php echo $html; ?></table> </body> </html> +---------------+-----------+------+-----+-------------------+-------+ | Field | Type | Null | Key | Default | Extra | +---------------+-----------+------+-----+-------------------+-------+ | id | int(11) | NO | PRI | NULL | | | name | char(10) | NO | | NULL | | | modified_date | timestamp | NO | MUL | CURRENT_TIMESTAMP | | | create_data | timestamp | YES | MUL | NULL | | +---------------+-----------+------+-----+-------------------+-------+ modified_dateの属性にはon update CURRENT_TIMESTAMPを設定し、 カラムのデータを変えるとmodified_dateが更新され、create_dataはそのままです。 SELECT id,name,modified_date,create_data,IF(`create_data`>CURDATE() - INTERVAL 0 DAY,'NEW',DATE_FORMAT(`create_data`,'%Y/%m/%d')) AS `ddd` FROM `data_data` http://okwave.jp/qa/q3058491.htmlでの方法がありました。 $daydiff = floor((strtotime($modified_date)-strtotime($create_data))/(3600*24)); if($daydiff==0){$datatext = 'new';}else{$datatext='';} 「あるカラムの情報が変わったら○○させる」といったことをいくつか追加していきたいので、 パフォーマンスが落ちることを少しでも避けるためにphpで処理するようにしましたが、一般的にはどちらを使うものなのでしょうか。 また、ifばかりにならないようにswitchを使ったのですが、ソートもいろいろ追加していきたく、そうなると今度はswitchが多くなってしまいます。 switchやifを使わずにスマートにやれる方法はないでしょうか。

    • ベストアンサー
    • PHP
  • 効率の良いSQL文の書き方を教えてください

    MySQLで開発をしています。 1回のSQLで、下記テーブルの内容を日付・ユーザ番号毎(日付・ユーザ番号が同じ時に同じレコード)に、 型番1個数、 型番2個数、 その他が2か3で型番2・品番1個数、 その他が2か3で型番2・品番1個数、 その他が2か3で型番2・品番1での売上小計、 その他が2か3で型番2・品番2個数での売上小計、 売上合計、 以上の各カラムを持つテーブルに再編して返したいのですが、 効率の良いやり方がわかりません。 どなたかよろしくお願いします。 テーブル ユーザ番号 日付   型番  品番   売上  その他 ----- --- --- --- --- ---  001     3/10    1    2     500    1  001     3/10    2    1      0    1  003     3/11    2    1     100    2  004     3/12    1    1     100    2  005     3/12    2    2      0     2  001     3/13    1    2     500    1  003     3/13    2    1     100    2  003     3/13    2    1      0     3  002     3/14    1    1     100    3  005     3/15    2    2     0      1

専門家に質問してみよう