SQL having 集約関数の絞り込み whereよりもレスポンスが遅い理由とは?
  • facebookページ
  • twitterページ
  • 2019.10.20

    SQL having 集約関数の絞り込み whereよりもレスポンスが遅い理由とは?

    group byによる集約関数の絞りこみ目的で使われるhaving句のサンプルコードを紹介します。

    以下、データベースとして、MySQLのサンプルデータベースEmployeesを使っています。SQL実行結果の表示にはphpMyAdminを使用しています。

    havingの基本的な使い方

    上記SQLは、dept_name(部署名)ごとの社員数を取得します。dept_emp(部署・社員紐付けテーブル)とdepartments(部署テーブル)を結合し、dept_no(部署番号)でグルーピングしています。

    havingにて、社員数30000以上の部署のみに絞込を行っています。

    SQL実行結果

    havingのサンプルコード

    平均値(avg)をhavingで絞り込む

    上記のSQLは、部署ごとの平均年収を取得しています。salaries(年収テーブル)とdept_emp(部署・社員紐付テーブル)、departments(部署テーブル)をjoinしています。

    年収が有効(salaries.to_date=9999-01-01)なもののみ対象に、dept_name(部署名)でグルーピングしています。

    havingで、avg(salary)=平均年収70000以上のデータに絞り込みをおこなっています。

    SQL実行結果

    【関連記事】
    SQLのgroup byサンプルコード集 count、like、join等の組み合わせ例

    重複レコードを取得するにはcount(*)を条件に組み込む

    上記SQLは、salaries(年収テーブル)の最新日付の重複数を取得しています。havingで、重複が1件以上のデータに絞り込みをおこなっています。

    SQL実行結果

    havingにサブクエリを使うサンプル

    havingの条件にサブクエリを使うことも可能です。

    上記SQLは、titles(肩書テーブル)に存在する全ての肩書の社員が揃っている部署を取得します。

    サブクエリでは、titles(肩書テーブル)、dept_emp(部署・社員紐付けテーブル)、departments(部署)テーブルをleft joinで結合し、dept_no(部署番号)でグルーピングしてdept_name(部署名)、title(肩書)を取得しています。

    メインクエリでは、サブクエリの結果をdept_name(部署名)でグルーピングし、dept_name(部署名)と所属する社員の肩書の種類数を取得。havingにて、titlesテーブルに存在する全肩書種類数(=7種類)の社員が揃っている部署のみ取得するよう絞り込みを行ってます。

    SQLを実行すると、こうなります。

    SQL実行結果

    whereとhavingの決定的な違いはレスポンス速度

    whereとhavingは同じように使えて、結果も同じです。

    例えば、以下の2つのクエリは、全く同じ結果になります。

    ※titles(肩書テーブル)から、emp_no(社員番号)20000以上のデータを取得するSQLです。

    しかし、explainで実行計画を確認してみると…

    where使用のSQLは、インデックスを使用して実行(key=PRIMARY)しています。

    一方having使用のSQLは、インデックス不使用(key=NULL)のテーブルフルスキャン(type=ALL)となっています。

    件数の少ない単純なクエリでは、さほどレスポンスに差は出ないかも知れません。しかし、基本的にはhavingは遅いものと考えておいて良いでしょう。

    having使用は、sumやcount、avgなどの集約関数の絞込時のみにしておきましょう。

    主要DBMSのHaving使用時の注意点

    Oracle Having 特に注意点なし

    LOB列、ネストした表またはVARRAYを条件に指定できない以外は、特に独自の注意点はありませんでした。

    関連)Oracleのhaving句解説

    MySQL Having 拡張使用でhavingにエイリアス使用可能

    標準SQLでは、having句でエイリアスを使うことはできないことになっています。MySQLでは独自の拡張により、having句でのエイリアスが使用可能になってます。

    関連)MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.19.3 MySQL での GROUP BY の処理

    SQL Server Having 特に注意点なし

    havingではtext、image、ntext型は使用できない点以外は特に独自の注意点はありませんでした。

    関連)HAVING (Transact-SQL) – SQL Server | Microsoft Docs

    PostgreSQL Having 特に注意点なし

    FOR NO KEY UPDATE、FOR UPDATE、FOR SHARE、FOR KEY SHAREを併用して使うことができない点以外は、特にhavingに関する独自の注意点はありませんでした。

    関連)PostgreSQLのHAVING句解説

    まとめ

    ポテパンダの一言メモ
    • havingはsumやavg、countなどの集約関数に絞り込みをおこなう
    • countとの組み合わせで、重複しているレコードの数を取得可能
    • havngにはサブクエリも使用可能
    • whereとhavingは同じように使えるが、havingはインデックスを使わないため遅くなる可能性が高い
    • 主要DBMSでは、havingの仕様に大きな違いはない

    ポテパンが提供するサービスについて

    本メディア「ポテパンスタイル」を運営する株式会社ポテパンは、エンジニアキャリア領域で複数サービスを提供しています。

    ポテパンフリーランス

    ポテパンフリーランス

    フリーランスエンジニアの方に高単価案件をご紹介しております。弊社ではフリーランス案件を常時300件ほど保有しており、その中からあなたに適した案件をご案内いたします。また、これから独立してフリーランスになる方の無料個別相談も承っております。フリーランスになった後の案件獲得方法やお金面(税金や保険など)についてお答えいたします!フリーエンジニアになりたい方向けのコンテンツも盛りだくさんです。

    ポテパンキャリア

    ポテパンキャリア

    エンジニア職専門の転職エージェントです。ポテパンキャリアでは、技術のわかるエージェントがあなたの転職をサポートします。エージェント自身がエンジニアなので、あなたと同じ目線で仕事内容や今後のキャリアについて一緒に考えることができます。年収800万円以上のハイスペック転職をご希望の方は「ポテパンプロフェッショナル」もご用意しておりますのでご利用下さいませ。

    ポテパンキャンプ

    ポテパンキャンプ

    ポテパンキャンプでは、RubyにてゼロからオリジナルのECサイトを作り上げてる3ヶ月間の実践型カリキュラムを提供しております。すでに本スクールの卒業生は、エンジニア職として様々な企業様に就職しております。なお、本スクールは受講料25万円と他社スクールに比べ格安となっており、またポテパンからご紹介させていただいた企業へ就職が決まった場合は、全額キャッシュバックいたします。



    株式会社ポテパンは、企業とエンジニアの最適なマッチングを追求しています。気になるサービスがあれば、ぜひ覗いてみてください!

    ポテクラバナー ポテプロバナー

    この記事をシェア

    • Facebookシェア
    • Twitterシェア
    • Hatenaシェア
    • Lineシェア
    pickup









    ABOUT US

    ポテパンはエンジニアと企業の最適なマッチングを追求する企業です。

    READ MORE

    ポテパンおすすめ案件