MySQLからの条件(計算)一致レコードの抽出方法 - PHPプロ!Q&A掲示板

2410

  • 200P

MySQLからの条件(計算)一致レコードの抽出方法

質問日時 / 2009年12月19日 18:33    回答数 / 9件

Questioner:  hamejiT  このエントリーをはてなブックマークに追加 

キーワード / MySQL    条件(計算値)    検索   

はじめまして、最近、php+MySQLを用い、ホームページの作成を始めたものです。
自分なりにネットで調べたのですが、どうにも解決できない問題に直面してしまったので、
皆様の知恵をお貸しいただけたら幸いです。

やりたい事はデータベースのグラフの2点(X,Y)と入力した点(x,y)の比較をし
その距離の少ない順に並べ変え、上位10個を表示させるプログラムを組みたいです。

例えば、データベースは[点], [X], [Y]とし
(A, 3, 4)、(B, 5, 12)、(C, 1, 1) とあるとします。

入力点を[0, 0]とすると、近い順には1.C、2.A、3.B
と表示されるプログラムを組みたいんです。

計算値(距離)は入力点により毎回変わるので
データベースにプリセットできないので、私が考えたのは
①新たに距離の列をデータベースに作成
②[X],[Y]のデータを抽出
③計算
④合計値の列にそれぞれの値を入力
⑤小さい順に並び替え
⑥合計値の列を削除
⑦結果表示
というものです。

具体的に行き詰ったコードを下に添付します。
ご教授いただけると助かります。よろしくお願いいたします。

また、もし上記の方法がまったく遠回りでセンスのないものでしたら、
その指摘もいただけると幸いです。
  1. //まずは設定
  2. $user = @ID;
  3. $pass = @pass;
  4. $host = @host;
  5. $database = @database;
  6. $table = @table;
  7.  
  8. //DB接続・データ取得
  9. $connect = mysql_connect($host, $user, $pass);
  10. mysql_select_db($database, $connect);
  11. $sql = "SELECT * FROM $table";
  12. $rs1 = mysql_query($sql, $db);
  13.  
  14. //列を増やす
  15. mysql_query("ALTER TABLE $table ADD `kyori` text NOT NULL FIRST , $database);
  16.  
  17. //各列よりX,Yの値を得て、計算値し、挿入
  18. while ($row = mysql_fetch_assoc($rs1)) {
  19.  //式は面倒なのでここでは±考慮してないです。
  20.  $dif = (x - $data['X']) + (y - $data['Y']);
  21.  mysql_query("UPDATE INTO $table (`kyori`, `point`, `x`, `y`) VALUES ('$dif', '$data['point']', '$data['X']', '$data['Y']')", $database);
  22. }
  23.  
  24. mysql_free_result($rs1);
  25. $rs2 = mysql_query("SELECT * FROM $table ORDER BY 'kyori'", $database);
  26.  
  27. while ($row = mysql_fetch_assoc($rs2)) {
  28.  echo $row['point']."点";
  29.  echo "距離は".$row['kyori']."です。";
  30. }
  31.  
  32. mysql_query("ALTER TABLE $tbl DROP 'kyori'");
  33. mysql_free_result($rs1);

この質問への意見の募集は締め切られ、ポイントは既に配分されました。
意見を投稿することはできますが、ポイントを受け取ることはできません。



ツリー一覧

┣A01blanc01回答にはならないかもしれませんが、 データベースの
┃┗A01-1hamejiTblanc01さん意見ありがとうございます。 やはりDB
┣A02win_php>>CODE // 選択した地点 $a = 0; $b = 0; /*
┃┣A02-1hamejiT忙しくて、このHPしばらく見られなかったです。 返事
┃┣A02-2hamejiTさっそく試させていただいたんですが・・・ 結果が
┃┗A02-3hamejiT上記のレス取り消しででお願いします。 大変失礼し
┃ ┗A02-3-1win_php上記のだとちょっと不具合ありそうですね。 usort()
┗A03NurseAngel未確認 >>CODE SELECT table.id AS ID , table.x
 ┗A03-1hamejiT貴重な意見ありがとうございます。 UPDATE whileは

回答一覧

並び替え:

A01
answererblanc01 [12月20日 01:12]

回答にはならないかもしれませんが、
データベースの使い方間違ってません?
普通は1処理でカラム追加したり消したりとはしないかと…

なぜ、計算結果を一旦DBに入れるんでしょう?
ソートのため??であれば、上記のようにカラム追加してまでDBにつっこむんでなくて、php側で配列やらなんやらでがんばってソートしたほうがいいですよ。

この意見に回答する

ツリーへ TOPへ

A01-1
replyerhamejiT [12月20日 12:22]

blanc01さん意見ありがとうございます。

やはりDB内に計算値を入れて、ソートしなおして、削除するのは邪道ですか・・・
phpのみでのプログラムの書き方がわからなかったのもあり、ああいう手順にいたりました。

同時アクセスがあった場合にはやはり一時的に作った列が影響してエラーになるんですかね・・・。

貴重な意見ありがとうございました。
php中心に作る方針とします。

この意見に回答する

ツリーへ TOPへ

A02 参考になった
answererwin_php [12月20日 03:20] (最終編集:12月20日 03:23)

  1. // 選択した地点
  2. $a = 0;
  3. $b = 0;
  4.  
  5. /*
  6. 省略
  7. */
  8.  
  9. while ($row = mysql_fetch_assoc($rs1)) {
  10.   // この時点で距離を求めて、配列に格納
  11.   $kyori = number_format(hypot(($row["X"]-$a),($row["Y"]-$b)),2);
  12.   $list[] = array($row["ten"] => $kyori);
  13.  
  14. }
  15.  
  16. // ソート
  17. asort($list);
  18.  
  19. $end = 0;
  20.  
  21. foreach($list as $k ){
  22.   foreach($k as $key => $value){
  23.     // $end 10で停止
  24.     if($end>9){
  25.       break;
  26.     } else {
  27.   echo "点".$key." 距離".$value."<br>";
  28.     }
  29.   $end++;
  30.   }
  31. }

こんな感じかなぁ。

この意見に回答する

ツリーへ TOPへ

A02-1
replyerhamejiT [12月21日 22:19]

忙しくて、このHPしばらく見られなかったです。
返事いただいたのに、反応なくて申し訳ないっす。

コードありがとうございます。
今から試してみて、また報告します。

この意見に回答する

ツリーへ TOPへ

A02-2
replyerhamejiT [12月22日 02:06]

さっそく試させていただいたんですが・・・

結果がうまくソートされてませんでした・・・。
何かなんででしょう・・・

この意見に回答する

ツリーへ TOPへ

A02-3
replyerhamejiT [12月22日 03:04]

上記のレス取り消しででお願いします。

大変失礼しました。
パラメーターをいくつかいじってたら、ちゃんと表示されました。
ありがとうございます。
ひとまず、解決いたしました。

今後はプログラム内でMySQLに列を作って、
削除すると言った事をせずに済むように
MySQLから呼び出して、php内で計算・ソート・表示できるように
しなければっていう次の課題ができました。

永遠に勉強ですね・・・。

この意見に回答する

ツリーへ TOPへ

A02-3-1 満足
replyerwin_php [12月22日 03:11] (最終編集:12月22日 03:15)

上記のだとちょっと不具合ありそうですね。
usort() でユーザー定義してみました。

試験してみたので、while()のあたりは修正ください。



  1. // 選択した地点
  2. $a = 0;
  3. $b = 0;
  4. $row["X"] = 1;
  5. $row["Y"] = 1;
  6. $row["X2"] = 0;
  7. $row["Y2"] = 1;
  8. $row["X3"] = 7;
  9. $row["Y3"] = 0.5;
  10.  
  11. $row["ten"] = "A";
  12. $row["ten2"] = "B";
  13. $row["ten3"] = "C";
  14.  
  15.  
  16. //while ($row = mysql_fetch_assoc($rs1)) {
  17.   // この時点で距離を求めて、配列に格納
  18.   $kyori = number_format(hypot(($row["X"]-$a),($row["Y"]-$b)),2);
  19.   $list[] = array("ten" => $row["ten"], "kyori" => $kyori);
  20.   $kyori = hypot(($row["X2"]-$a),($row["Y2"]-$b));
  21.   $list[] = array("ten" => $row["ten2"], "kyori" => $kyori);
  22.   $kyori = hypot(($row["X3"]-$a),($row["Y3"]-$b));
  23.   $list[] = array("ten" => $row["ten3"], "kyori" => $kyori);
  24. //}
  25.  
  26. function cmp($a, $b){
  27.  
  28.     if($a["kyori"] > $b["kyori"]){
  29.         return 1;
  30.     }else if($a["kyori"] < $b["kyori"]){
  31.         return -1;
  32.     }else{
  33.         return 0;
  34.     }
  35. }
  36.  
  37.  
  38. usort($list, "cmp");
  39.  
  40.  
  41. for($i=0; $i<10; $i++){
  42. foreach($list[$i] as $k => $v){
  43.   if($k == 'ten'){
  44.   echo "点".$v;
  45.   
  46.   } else if($k == 'kyori'){
  47.     
  48.     echo " 距離".$v."<br>";
  49.   }
  50.  
  51. }
  52. }

この意見に回答する

ツリーへ TOPへ

A03 参考になった
answererNurseAngel [12月20日 12:59] (最終編集:12月21日 01:42)

未確認

  1. SELECT table.id AS ID , table.x AS X , table.y AS Y
  2.  , ( table.x - $x + table.y - $y AS kyori )
  3. FROM table
  4.  ORDER BY 
  5.    ( table.x - $x + table.y - $y )

とか。
もっと効率いい方法もありそうだけど。


表示系ではなく取得系で繰り返し構文を使用するのはよくないので
出来る限り避けるべきです。

つうかALTER TABLEをプログラムに組み込むとか初めて見た。


あと質問の場合だとUPDATEをwhileで回してるのは全く意味がないです。
↓だけでいいはず
  1. UPDATE table SET kyori=(
  2.  x -$x + y - $y
  3. )

この意見に回答する

ツリーへ TOPへ

A03-1
replyerhamejiT [12月21日 22:26]

貴重な意見ありがとうございます。

UPDATE whileはどこぞのHPから引用させていただいた構文だったと記憶してます。
ALTER TABLEはphpとMySQLの構文を混ぜ込んだ、完全に自作ですが・・・

独学(とくにホームページ中心)なせいか、そういうセンス?に疎いです。
ご指摘のコード試して、頑張ってみます。

わざわざ書き込みに追加訂正までいただき、ありがとうございます。

この意見に回答する

ツリーへ TOPへ

<<質問一覧へ



Pick Up Q&A

Q
PHPのHTML埋め込み記述について
 このエントリーをはてなブックマークに追加 
A
$_POST["data"] == "男" ? $val = "checked" : $val = "" ; の意味は以下と同じです。 if($_POST["data"] == "男"){ $val = "checked; } e...

>>続きを読む

kende様のご指摘通り、三項演算子を使用する際には、コードの複雑度などを考慮する必要がありますね。書きやすさと共に可読性も追求したいところですね。

▲解説者:岡本(アシアル株式会社 教育コーディネーター兼 システムエンジニア)