質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.77%

Mysql の SELECT 表記について

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 604

score 29

以下のコードですが、xxxテーブルからデータを抽出して表示したいのですが、⇒矢印の行を追加すると表示時間が異常に遅くなり、抽出データの量によっては timeout することがあります。表示時間を短くしtimeoutを避けるためにはどうしたらよろしいでしょうか?ご教授お願い致します。

<追記>
create table xxx (id int, AAA varchar(100), BBB varchar(100),CCC varchar(100),DDDvarchar(20));
AAA   BBB    CCC    DDD
====================
チョコ  170円 菓子類   111A
チョコ  160円 菓子類 111A
アイス  200円 アイス類 111B

ざっくりいうと、DDDの値が同一なら、AAAの値を重複させずに表示させたいのです。
(表示結果が「チョコ、チョコ、アイス」ではなく「チョコ、アイス」にしたい)

<?php

    $pdo = new PDO("mysql:host=xxx; dbname=db; charset=utf8", "xxx", "pass", array( PDO::ATTR_EMULATE_PREPARES => false ) );
    $sql = "select * from xxx where 1 = 1 ";
    $condition = array();

    if( !empty( $_REQUEST["drug"] ) ){
    $sql = $sql . " and ( AAA like :aaa or BBB like :bbb or CCC like :ccc  ) "; 
  ⇒$sql = $sql . " and ( id IN(SELECT min(id) FROM xxx GROUP BY DDD)  ) ";

        $condition[":aaa"] = "%{$_REQUEST["aaa"]}%";
                $condition[":bbb"] = "%{$_REQUEST["bbb"]}%";
           $condition[":ccc"] = "%{$_REQUEST["ccc"]}%";

    }

    $statement = $pdo->prepare( $sql );
    $statement->execute( $condition );
    $results = $statement->fetchAll();

foreach ($results as $result) {

print $result['AAA'];
}
?>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • XNXSXMXR

    2019/12/05 09:46

    「⇒」のクエリで最小の id を求めていますが、この条件を入れると「160円」のデータはヒットしなくなりませんか?

    キャンセル

  • alkeran

    2019/12/05 10:14

    初心者のため的を得ていない返答なら申し訳ありません。160円のチョコは表示させたくありません。DDDのカラムでお菓子のコードが一緒ならAAAカラムの表記は1種類にしたいのです。ただ、今回は表示はできるのですが、それまでの時間がものすごくかかってしまいます。

    キャンセル

  • XNXSXMXR

    2019/12/05 10:18

    なるほど、表示されなくても良いのが織り込み済みということですね。

    キャンセル

回答 2

checkベストアンサー

0

他の回答者様にもご指摘があるように、どこでどのように遅くなっているか「実行計画」(explain)を行ってみる必要があるかと思います。

SQLを直接実行できる環境(コンソールだったりphpMyAdminだったり他ツールでも)はありますか?

explain analyse
select * from xxx where 1 = 1 
 and ( AAA like '%チ%' or BBB like '%円%' or CCC like '%類%'  )
 and (id in (select min(id) from xxx group by DDD));

※上記「%チ%」や「%円%」は適当に指定しています。
実際にブラウザで入力している値を「%」と「%」の間にセットしてみてください。

これを実行し、結果を質問欄に追記してください。
何か原因が見つかるかもしれません。

思ったのが、LIKE検索は全件検索しに行くので、データ件数が多いほど時間がかかります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/06 22:15

    以下のコードです。
    explain analyse
    select * from xxx where 1 = 1
    and ( AAA like '%チ%' )
    and (id in (select min(id) from xxx group by DDD));

    キャンセル

  • 2019/12/07 21:10

    1つスペルミスがありました。
    「explain analyse」ではなく、「explain analyze」でした。すみません。

    あと、こちらで同様のテーブルと8万件のレコードを作って試してみましたが、1~2秒で結果が取得できました。

    質問者さまの環境と異なるので単純な比較ができないのですが、実行計画のクエリ(スペルを直して)をもう一度実行してみてください。

    ●マシンスペック(仮想マシン)
    ・CPU ... i5 2.5GHz (1コア)
    ・メモリ ... 1024MB
    ・MySQL ... Ver.8.0.18

    ■実行結果
    mysql> explain analyze
    -> select * from xxx2 where 1 = 1
    -> and ( AAA like '%チ%' )
    -> and (id in (select min(id) from xxx2 group by DDD));
    +---------------------------------------------------------------------------+
    | EXPLAIN |
    +---------------------------------------------------------------------------+
    | -> Filter: ((xxx2.AAA like '%チ%') and <in_optimizer>(xxx2.id,xxx2.id in (select #2))) (cost=8069.75 rows=8867) (actual time=844.340..1566.456 rows=6 loops=1)
    -> Table scan on xxx2 (cost=8069.75 rows=79815) (actual time=0.030..402.315 rows=81798 loops=1)
    -> Select #2 (subquery in condition; run only once)
    -> Table scan on <temporary> (actual time=0.005..0.026 rows=10 loops=1)
    -> Aggregate using temporary table (actual time=844.145..844.202 rows=10 loops=1)
    -> Table scan on xxx2 (cost=8069.75 rows=79815) (actual time=0.011..373.403 rows=81798 loops=1)
    |
    +---------------------------------------------------------------------------+
    1 row in set (1.57 sec)

    キャンセル

  • 2019/12/26 16:13

    返信が遅れまして、申し訳ございませんでした。
    SELECT DISTINCT により、時間がかからず表示することができました。
    解決方法を提案していただいたXNXSXMXRさんをベストアンサーにしたいと思います。
    他の皆様もありがとうございました。

    キャンセル

0

質問に CREATE TABLE, CREATE INDEX を追記してください。
MySQL SQL実行計画の疑問解決には「とりあえずEXPLAIN」しよう も質問に追記できた方が良いです。

 ⇒$sql = $sql . " and ( id IN(SELECT min(id) FROM xxx GROUP BY DDD)  ) ";

DDD列とid列でインデックスが設定されていなければインデックスを追加してみては?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/05 09:40

    有償サイトや対面のセミナーで勉強した方がよろしいかと。

    キャンセル

  • 2019/12/05 09:46

    各列もなるべくわかり易いネーミングに書き直したほうが良いんですけどね。
    昔、NECが作ったかアドバイスしたCOBOLで項目名が連番で統一されているシステムが酷すぎて、システム部の部長の了解を取って全部作り直したことがあります。項目名のミスが原因のバグがボロボロ見つかりました。全面的に作り直して、同じハードウェア・同じデータ量で15時間かかっていたバッチが1時間で終わりました。

    キャンセル

  • 2019/12/05 09:48

    コードやデータは https://teratail.com/help/question-tips#questionTips3-7 の [コード] に修正してください。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る