• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:効率的なSQL文をご教授ください。)

効率的なSQL文の作成方法

このQ&Aのポイント
  • MySQLの初級者の方に効率的なSQL文の作成方法についてご説明します。
  • テーブル構造の中で要件に合わせた出力を行いたい場合、JOINを使うことで効率的なSQL文を作成することができます。
  • 具体的な例として、記事の関連記事数を取得するSQL文をご紹介します。

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

  • ベストアンサー
  • nda23
  • ベストアンサー率54% (777/1415)
回答No.3

以下のSQLでいけると思います。 select max(C.name) as category_name, count(C.cid) as count_cid from (article_category A inner join (select aid from article_flag where display<>2) B on A.aid=B.aid) inner join category C on A.cid=C.cid group by A.cid

kayakiss
質問者

お礼

ご回答ありがとうございます。 こちらのSQL文を元に、少し応用した結果、 最初10秒近くかかっていたものが、0.07秒まで短縮できました。 今後もさらに精進して鍛えていきたいと思います。 このたびはありがとうございました!

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (2)

  • nora1962
  • ベストアンサー率60% (431/717)
回答No.2

素直に select category.name, count(*) from article_category join article_flag on article_category.aid=article_flag.aid and article_flag.display=1 join category on article_category.cid=category.cid group by category.name; ではダメですか。

kayakiss
質問者

お礼

ご回答ありがとうございます。 例はあくまでも要点だけをまとめた簡易なもので、 実際のSQL文には、そのほかにもJOINが10個以上あるような内容です。 ご回答いただいた型で進めますと、 早い時で7秒、遅いと10秒程度かかります。

全文を見る
すると、全ての回答が全文表示されます。
  • nda23
  • ベストアンサー率54% (777/1415)
回答No.1

MySQLのバージョンを提示してください。 4と5ではサブクエリが使えるかどうかの 違いがあり、これだけで全く異なるSQLに なります。

kayakiss
質問者

お礼

ご回答ありがとうございます。 MySQLのバージョンは5.1.59になります。 よろしくお願いいたします。 私の考えうる狭い範囲でのサブクエリも試しましたが、 どれもむしろ逆に重くなってしまい困っています。 サーバがホスティングの共有MySQLなので、 そこまでパフォーマンスは高くありません。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • SQLが走らない

    なぜかSQLが走りません。 エラーもでません。 カテゴリーリンクを押したら、そのカテゴリに書いた記事が表示されるようにしています。 $stmt = $pdo->query('SELECT * FROM ' . DATABASE_TABLE_ARTICLE . ' LEFT JOIN ' . DATABASE_TABLE_CATEGORY . ' USING (cid) WHERE cid = :cid ORDER BY date DESC'); $stmt->bindValue(':cid', $cid, PDO::PARAM_INT); if (!$stmt) { db_error($pdo->errorInfo()); } 1.$cidの値は取れています。 2.WHERE文をなくすと文が表示されます。 3.:cidに直接数字4とかを入れると大丈夫です。 4.cid = :cidのところがおかしいようです。 この記述どこか間違っているでしょうか? ほかの動いている部分のスクリプトをもってきているのですが・・・。

  • SQL文のINNER JOIN内での条件付けについて質問です

    SQLの質問です。 先程も質問させて頂いた件(http://okwave.jp/qa4089307.html)に派生した問題なのですが、 Accessのクエリにて SELECT A.*FROM grade_points AS A INNER JOIN [SELECT MAX(enforcement_date) AS MaxDate,grade_id FROM grade_points WHERE (enforcement_date)<=date() GROUP BY grade_id]. AS B ON (A.grade_id = B.grade_id) AND (A.enforcement_date = B.MaxDate); (前回の件のクエリにWHERE (enforcement_date)<=date() の条件を追加しました) というクエリを作ると、SQLを書いた直後の保存前はちゃんと動くのですが、保存後に閉じてから実行しようとすると「入力テーブルまたはクエリ(上記[]内SQL文)が見つかりません」というエラーになってしまいます。 INNER JOIN内のSQLにWhere条件は使えないのでしょうか??保存前は動くので不思議でなりません… お手数ですがどなたかご意見よろしくお願い致します。

  • SQL詳しい方、助けてください。

    こんにちは。 UPDATE テーブルA SET フィールドA1 = '1' WHERE フィールドA2 =(SELECT フィールドB1 FROM テーブルB WHERE フィールドB2 = 'C0' OR フィールドB2 = 'C2' AND フィールドB3='') AND フィールドA3 = '' AND フィールドA4 <> '' というSQLを作成して、動作していたので安心していたら、 テーブルBのレコード数は1件のみだと思っていたら、複数存在する場合があるとのことで、 テーブルBのレコードを追加してみたところ、、 【サブクエリは複数の値を返しました。サブクエリが = 、!= 、<、<= 、>、>= のあとに続く場合や、 サブクエリが 1 つの式として使われる場合に複数の値は許可されません。】 というエラーで終了するようになってしまいました。 そこで、 UPDATE テーブルA AS A INNER JOIN テーブルB AS B ON A.フィールドA2 = B.フィールドB1 SET A.フィールドA1 ='1' WHERE B.フィールドB2 = 'C0' OR B.フィールドB2 = 'C2' AND B.フィールドB3='' AND A.フィールドA3='' AND A.フィールドA4 <> '' としてみました。 なんだか混乱してきて、結合条件があっているかが 自分でもよくわかんなくなっていますが。 しかも、 上記のSQLをSQL SERVER 2000のクエリアナライザで 実行すると、 【キーワード 'inner' 付近に正しくない構文があります。】 というエラーが・・・。 INNER 以下はいろいろおかしいんだろうな・・・と 思っていたのですが、まさか、そんなしょっぱなで引っかかるとは思いませんでした。 いろいろ、記述方法を変更してみたり、考えたんり したんですけど、情けないことにさっぱり解りません。 どなたかお力をお貸しください。 お願いします。

  • SQLに条件を追加したいのですが方法が分かりません

    <?php $search_query = get_search_query(); ?> <?php global $wpdb; ?> <?php $sql = " SELECT COUNT(*) AS all_count FROM wp_posts AS post INNER JOIN ( SELECT * FROM wp_postmeta WHERE meta_key='single_rss_feed1' ) AS feed ON post.ID = feed.post_id LEFT JOIN ( SELECT * FROM wp_postmeta WHERE meta_key = '_thumbnail_id' ) AS thumbnail ON post.ID = thumbnail.post_id LEFT JOIN wp_posts AS attachment ON thumbnail.meta_value = attachment.ID LEFT JOIN ( SELECT category.object_id AS post_id, GROUP_CONCAT(category.name ORDER BY category.term_id) AS category_names, GROUP_CONCAT(category.slug ORDER BY category.term_id) AS category_slugs FROM ( SELECT sub_a.name, sub_a.slug, sub_c.object_id, sub_a.term_id FROM wp_terms AS sub_a LEFT JOIN wp_term_taxonomy AS sub_b ON sub_a.term_id = sub_b.term_id LEFT JOIN wp_term_relationships AS sub_c ON sub_b.term_taxonomy_id = sub_c.term_taxonomy_id WHERE sub_b.taxonomy = 'category' ) AS category GROUP BY category.object_id ) AS category ON post.ID = category.post_id WHERE post.post_type = 'post' AND post.post_status = 'publish' AND post.post_content LIKE %s OR post.post_title LIKE %s OR post.post_excerpt LIKE %s) $query = $wpdb->prepare($sql, "%$search_query%", "%$search_query%", "%$search_query%"); $results = $wpdb->get_results($query); ?> <?php if ($results) : ?> <ul> <?php foreach ($results as $result) : ?> <li> <?php echo "<a href=\"{$result->post_url}\">{$result->post_title}</a>"; echo $result->post_date; echo $result->category_names; if (empty($result->comment_count)) { echo 'コメントなし'; } else { echo "{$result->comment_count}件のコメント"; } echo $result->post_excerpt; echo "<a href=\"{$result->post_url}/#more-{$result->post_id}/\">続きを読む</a>"; if (empty($result->thumbnail_url)) { $result->thumbnail_url = 'noimage.jpg'; } echo "<img src=\"{$result->thumbnail_url}\">"; ?> </li> <?php endforeach; ?> </ul> <?php endif; ?> ※追加したい条件 $categories = []; foreach (get_categories() as $category) { $categories[$category->cat_ID] = $category; } function set_other_data($post) { // アイキャッチIDを取得 $post_thumbnail_id = get_post_thumbnail_id($post); // アイキャッチ画像の確認 if ($post_thumbnail_id) { // 存在する $image_src = wp_get_attachment_image_src($post_thumbnail_id); // サムネイルの画像URLを設定 $post->thumbnail = $image_src[0]; } else { // 存在しない $post->thumbnail = 'noimage.jpg'; } // カテゴリーIDを取得 $post->categories = wp_get_post_categories($post->ID); // コメントテキスト if (0 == $post->comment_count) { // コメントなし $post->comments = __('No Comments'); } else { // コメントあり $post->comments = $post->comment_count.'件のコメント'; } // コメントリンク $post->comments_link = get_comments_link($post->ID); }

    • ベストアンサー
    • PHP
  • PHPの簡易データ検索プログラムを書いていますがページャーを使ったデー

    PHPの簡易データ検索プログラムを書いていますがページャーを使ったデータ連動でうまくいかないところがあります。問題は1のデータ数取得がどのように2回(カウント+本検索)クエリを投げれば良いか判りません。どうかご教授いただきますようお願いします。 <?php require_once "./rank/config.php"; require_once("Pager/Pager.php"); //【1】カウント用データベースに接続 $link = mysql_connect($server, $usr, $pass); $db = mysql_select_db($mydb, $link); $query = "SELECT COUNT(*) FROM detail WHERE category = '".$ID."'"; $count = mysql_query($query); //【1】データ数の取得 $limit = $count; $page = empty($_GET['p']) ? 1: $_GET['p']; $offset = ($page - 1) * $limit; // クエリ条件部分 $query = "SELECT * FROM detail"; $query .= " where 1"; $query .= " and category = '".$ID."'"; $query .= " limit {$limit} offset {$offset}"; $flag = true; //MySQLデータベースに接続 if(!$link = mysql_connect($server, $usr, $pass)){ $flag = false; } //データベース選択 if(!$db = mysql_select_db($mydb, $link)){ $flag = false; } //lolipop用 mysql_set_charset("utf8"); //クエリ実行 if(!$result = mysql_query($query)){ $flag = false; } if(mysql_num_rows($result)==0){ echo 'データ件数は0件です'; } $rows = mysql_num_rows($result); if ($flag == true){ //メイン出力部 while($row = mysql_fetch_array($result,MYSQL_ASSOC)) { $list[] = array(category =>$row["category"],area=>$row["area"]); } }else{ echo 'データベース接続エラー'; } echo "<b>", $rows, "</b>件HITしました<br />\n"; $params = array( 'mode' => 'sliding', 'perPage' => $limit, 'itemData' => $list, 'firstPagePre'=>'=', "firstPageText"=>"TOP", "firstPagePost"=>"=", "lastPagePre"=>"=", "lastPageText"=>"LAST", "lastPagePost"=>"=", ); $pager = & Pager::factory($params); $navi = $pager->getLinks(); print($pager->numItems()."件中<br/>"); $scope = $pager->getOffsetByPageId(); print($scope['0']."件目から".$scope['1']."件目を表示 <br/>"); $ary = $pager->getPageData(); foreach ($ary AS $key => $value) { echo "<br>□1<br>".$value["category"]."<br>"; echo "□2<br>".$value["area"]."<br>"; echo "<hr>"; } echo $navi['all']; //SQLの解放 mysql_free_result($result); mysql_close($link); ?>

    • 締切済み
    • PHP
  • SQL文(クエリ)をご教授ください。

    SQL文(クエリ)をご教授ください。 Oracle8において下記のようなテーブルが有り、復数台の装置に関して 毎日365日データを蓄積しています。 日によってデータが採取できない装置があるため、号機に抜けが 生じる事があります。 また実際は装置は14000台程度のデータを収集しています テーブル名:t_temp 号機  日付   基板温度 Disk温度 外気温度 01  2010/03/01  50    70    25 02  2010/03/01  49    73    25 03  2010/03/01  52    72    25 04  2010/03/01  49    71    25 01  2010/03/02  56    77    26 02  2010/03/02  57    75    26 04  2010/03/02  55    74    27 01  2010/03/03  49    71    24 03  2010/03/03  50    72    25 04  2010/03/03  48    70    23      以下データは続く このテーブルから、以下のような2パターンの検索をしたいと考えています。 1.号機ごとに、基板温度が50度以上となった最初の日付と基板温度を検索 2.号機ごとに、基板温度が最高温度の日付と基板温度を検索 参考書なども眺めてみたのですが、糸口が見出せずにいます。 クエリ例と、その説明を説明をいただけると幸いです。 実行環境は、MS-ACCESSからパススルークエリで実行しています。 補足が必要でしたら、ご指摘いただけると幸いです。 皆様のお力を借用したく、お願いいたします。

  • SQL文をご教授願います

    SQL文をご教授願います。 以下のようなテーブルを仮定しています。 A   B    C   D ---------------------- 10  100  1203 A 10  200  1204 B <--- 取得したい 11  300  1203 C 11  300  1204 D <--- 12  400  1206 D 12  500  1207 E <--- ・ ・ A列をー意にして、A列・D列のデータを取得したい 条件 Bの大きい方を取得する Bの値が同じ場合はCの大きい方を取得する。 (A列には同じデータが2以上あるとします) (C列には同じデータはありません) 欲しい結果 A   D -------- 10 B 11 D 12 E

  • 効率の良い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

  • 効率的なSQL文が思いつきません

    いつもお世話になっております。 前回(多分1年ほど前) 質問させて頂いた際は丁寧に回答頂きまして感謝しております。 自分であれこれと思いめぐらせてみたのですが、これだと思うSQL文が思いつきませんでして、早速ですが質問をさせて頂きたいと思います。 テーブル構造 user_id ques_id result (プライマリーは別途)  001  1   1  002  1   0  003  1   1  004  1   1  002  2   1  003  2   0  001  3   1 … 学習のデータベースの初答の場合の結果を記録するものです。 user_idとques_idでユニークです。 例えば、1レコード目はユーザ001が 問題番号1を正解(result=1)したことを表します。 ※任意問題に対してすべてのユーザが  問題を解いているとは限りません。 ここで、取り出したい情報は ある任意の問題セット(例: (1,3,4,5))を全て解いているユーザ のuser_idとその問題セットの正答率です。 理想的な結果としては ある問題セットに対して user_id 正答率  001 3/4 のように出力されて欲しいです。 *私が考えたこと (SELECT * from テーブル WHERE ques_id = 1) as t1 LEFT JOIN (SELECT * from テーブル WHERE ques_id = 3) as t2 USING(user_id) って繋げてみて・・・どうするんだろう(???) これでもなんかいびつな感じがとってもします。 って感じです。 アドバイス頂ければ幸いです。

    • ベストアンサー
    • MySQL
  • 3つのテーブルを結合した場合のWHERE

    MySQLで3つのテーブルを結合した場合のWHEREがよくわかりません。 まず、下のような2つのテーブルがあるとします。 【テーブルaa】 ID | Name -------------- 1 | x 2 | y 3 | z 【テーブルbb】 ID | hizuke | category --------------------- 1 | stamp1 | a 1 | stamp2 | b 1 | stamp3 | c 2 | stamp1 | a 2 | stamp2 | d 3 | stamp1 | c この2つのテーブルを結合して、同じIDでhizukeが最大値のデータを抽出するクエリは、 http://okwave.jp/qa/q6918385.htmlを参考にして、 SELECT aa.Name, bb.category FROM bb INNER JOIN aa ON aa.ID = bb.ID where (bb.ID, bb.hizuke) in (SELECT bb.ID, max(bb.hizuke) FROM bb group by bb.ID ) ; でできました。 しかし、もう1つテーブルを結合すると期待した結果が得られなくなってしまいました。 【テーブルcc】 category | choice --------------------- a | ss b | tt c | uu というテーブルがあって、上のクエリで得られた bb.categoryと cc.categoryをリンクして、choiceを取得しようとしたのですがうまくいきません。 SELECT aa.Name, bb.hizuke, bb.category, cc.choice FROM bb INNER JOIN cc ON bb. category = cc. category INNER JOIN aa ON aa.ID = bb.ID where (bb.ID, bb.category, bb.hizuke) in (SELECT bb.ID, bb.category, max(bb.hizuke) FROM bb group by bb.ID ); というクエリでは、ダメなようです。 INNER JOINを入れ子にしたり、いろいろと試したのですがどうにもうまくいきません。 どうも私の力では解決困難なようです。どなたかヘルプを。