MySQL 8.0 リファレンスマニュアル


13.2.10 SELECT ステートメント

SELECT
    [ALL | DISTINCT | DISTINCTROW ]
    [HIGH_PRIORITY]
    [STRAIGHT_JOIN]
    [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
    [SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
    select_expr [, select_expr] ...
    [into_option]
    [FROM table_references
      [PARTITION partition_list]]
    [WHERE where_condition]
    [GROUP BY {col_name | expr | position}, ... [WITH ROLLUP]]
    [HAVING where_condition]
    [WINDOW window_name AS (window_spec)
        [, window_name AS (window_spec)] ...]
    [ORDER BY {col_name | expr | position}
      [ASC | DESC], ... [WITH ROLLUP]]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [into_option]
    [FOR {UPDATE | SHARE}
        [OF tbl_name [, tbl_name] ...]
        [NOWAIT | SKIP LOCKED]
      | LOCK IN SHARE MODE]
    [into_option]

into_option: {
    INTO OUTFILE 'file_name'
        [CHARACTER SET charset_name]
        export_options
  | INTO DUMPFILE 'file_name'
  | INTO var_name [, var_name] ...
}

SELECT は、1 つ以上のテーブルから選択された行を取得するために使用され、UNION ステートメントとサブクエリーを含めることができます。 セクション13.2.10.3「UNION 句」およびセクション13.2.11「サブクエリー」を参照してください。 SELECT ステートメントは、WITH 句で始まり、SELECT 内でアクセス可能な共通テーブル式を定義できます。 セクション13.2.15「WITH (共通テーブル式)」を参照してください。

SELECT ステートメントのもっとも一般的に使用される句は次のとおりです。

  • select_expr は、取得するカラムを示します。 少なくとも 1 つの select_expr が存在する必要があります。

  • table_references は、行を取得する 1 つまたは複数のテーブルを示します。 その構文については、セクション13.2.10.2「JOIN 句」で説明されています。

  • SELECT では、table_reference のテーブル名の後にパーティションまたはサブパーティション (あるいはその両方) のリストを含む PARTITION を使用した明示的なパーティション選択がサポートされています (セクション13.2.10.2「JOIN 句」 を参照)。 この場合、行はリストされているパーティションからのみ選択され、テーブルのほかのパーティションはすべて無視されます。 詳細および例については、セクション24.5「パーティション選択」を参照してください。

  • WHERE 句 (指定されている場合) は、選択されるために行が満たす必要のある 1 つまたは複数の条件を示します。where_condition は、選択される各行に対して true に評価される式です。 WHERE 句がない場合、このステートメントはすべての行を選択します。

    WHERE 式では、集計 (グループ) 関数を除き、MySQL でサポートされている任意の関数および演算子を使用できます。 セクション9.5「式」および第12章「関数と演算子を参照してください。

SELECT を使用して、どのテーブルも参照せずに計算された行を取得することもできます。

例:

mysql> SELECT 1 + 1;
        -> 2

テーブルが参照されない状況では、ダミーのテーブル名として DUAL を指定することが許可されます。

mysql> SELECT 1 + 1 FROM DUAL;
        -> 2

DUAL は純粋に、すべての SELECT ステートメントに FROM や、場合によってはその他の句が存在することを要求するユーザーの便宜のために用意されています。 MySQL は、これらの句を無視する可能性があります。 MySQL では、テーブルが参照されない場合でも FROM DUAL は必要ありません。

一般に、使用される句は、正確に構文の説明で示されている順序で指定する必要があります。 たとえば、HAVING 句は、すべての GROUP BY 句のあとで、かつすべての ORDER BY 句の前にある必要があります。 INTO 句は、構文の説明で示されている任意の位置に指定できますが、特定のステートメント内に指定できるのは一度のみで、複数の位置には指定できません。 INTO の詳細は、セクション13.2.10.1「SELECT ... INTO ステートメント」を参照してください。

select_expr 項のリストは、どのカラムを取得するかを示す選択リストで構成されています。 これらの項はカラムや式を指定するか、または * の短縮形を使用できます。

  • 1 つの修飾されていない * のみから成る選択リストは、すべてのテーブルのすべてのカラムを選択するための短縮形として使用できます。

    SELECT * FROM t1 INNER JOIN t2 ...
  • tbl_name.* は、指定されたテーブルのすべてのカラムを選択するための修飾された短縮形として使用できます。

    SELECT t1.*, t2.* FROM t1 INNER JOIN t2 ...
  • テーブルに非表示カラムがある場合、* および tbl_name.* には非表示カラムは含まれません。 非表示カラムを含めるには、明示的に参照する必要があります。

  • 修飾されていない * を選択リスト内のほかの項目とともに使用すると、解析エラーが生成される可能性があります。 この問題を回避するには、修飾された tbl_name.* 参照を使用します。:

    SELECT AVG(score), t1.* FROM t1 ...

次のリストは、その他の SELECT 句に関する追加情報を示しています。

  • AS alias_name を使用して、select_expr にエイリアスを指定できます。 エイリアスは式のカラム名として使用され、GROUP BYORDER BY、または HAVING 句で使用できます。 例:

    SELECT CONCAT(last_name,', ',first_name) AS full_name
      FROM mytable ORDER BY full_name;

    select_expr にエイリアスとして識別子を指定する場合、AS キーワードはオプションです。 前の例は、次のように記述することもできました。

    SELECT CONCAT(last_name,', ',first_name) full_name
      FROM mytable ORDER BY full_name;

    ただし、AS はオプションであるため、2 つの select_expr 式の間のカンマを忘れると、軽微な問題が発生する可能性があります。MySQL は、2 番目の式をエイリアスとして解釈します。 たとえば、次のステートメントでは、columnb はエイリアスとして処理されます。

    SELECT columna columnb FROM mytable;

    このため、カラムのエイリアスを指定するときは AS を明示的に使用するようにすることをお勧めします。

    WHERE 句が実行されるときはまだカラム値が決定されていない可能性があるため、WHERE 句内でカラムのエイリアスを参照することは許可されません。 セクションB.3.4.4「カラムエイリアスに関する問題」を参照してください。

  • FROM table_references 句は、行を取得する 1 つまたは複数のテーブルを示します。 複数のテーブルを指定すると、結合が実行されます。 結合構文については、セクション13.2.10.2「JOIN 句」を参照してください。 指定されたテーブルごとに、オプションでエイリアスを指定できます。

    tbl_name [[AS] alias] [index_hint]

    インデックスヒントを使用すると、クエリー処理中にインデックスを選択する方法に関する情報がオプティマイザに提供されます。 これらのヒントを指定するための構文については、セクション8.9.4「インデックスヒント」を参照してください。

    代わりの方法として SET max_seeks_for_key=value を使用して、MySQL にテーブルスキャンの代わりにキースキャンを強制的に実行させることができます。 セクション5.1.8「サーバーシステム変数」を参照してください。

  • データベースを明示的に指定するために、デフォルトデータベース内でテーブルを tbl_name または db_name.tbl_name として参照できます。 カラムを col_nametbl_name.col_name または db_name.tbl_name.col_name として参照できます。 参照があいまいにならないかぎり、カラム参照のために tbl_name または db_name.tbl_name プリフィクスを指定する必要はありません。 より明示的なカラム参照形式を必要とするあいまいさの例については、セクション9.2.2「識別子の修飾子」を参照してください。

  • テーブル参照は、tbl_name AS alias_name または tbl_name alias_name を使用してエイリアス設定できます。 次のステートメントは同等です。

    SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
      WHERE t1.name = t2.name;
    
    SELECT t1.name, t2.salary FROM employee t1, info t2
      WHERE t1.name = t2.name;
  • カラム名、カラムのエイリアス、またはカラム位置を使用して、出力のために選択されたカラムを ORDER BY および GROUP BY 句で参照できます。 カラム位置は整数であり、1 から始まります。

    SELECT college, region, seed FROM tournament
      ORDER BY region, seed;
    
    SELECT college, region AS r, seed AS s FROM tournament
      ORDER BY r, s;
    
    SELECT college, region, seed FROM tournament
      ORDER BY 2, 3;

    逆の順序でソートするには、ソートに使用する ORDER BY 句内のカラムの名前に DESC (降順) キーワードを追加します。 デフォルトは昇順です。これは、ASC キーワードを使用して明示的に指定できます。

    ORDER BY がカッコで囲まれたクエリー式内で発生し、外部クエリーにも適用される場合、結果は未定義であり、将来のバージョンの MySQL で変更される可能性があります。

    カラム位置の使用は、この構文が SQL 標準から削除されたため非推奨です。

  • MySQL 8.0.13 より前では、MySQL は GROUP BY カラムの明示的な ASC または DESC 指定子を許可する非標準の構文拡張をサポートしていました。 MySQL 8.0.12 以降では、グループ化関数を使用した ORDER BY がサポートされているため、この拡張機能を使用する必要はなくなりました。 (Bug #86312、Bug #26073525) これは、GROUP BY の使用時に次のように任意のカラムでソートできることも意味します:

    SELECT a, b, COUNT(c) AS t FROM test_table GROUP BY a,b ORDER BY a,t DESC;

    MySQL 8.0.13 では、GROUP BY 拡張機能はサポートされなくなりました: GROUP BY カラムの ASC または DESC 指定子は許可されていません。

  • ORDER BY または GROUP BY を使用して SELECT のカラムをソートする場合、max_sort_length システム変数で指定された初期バイト数のみを使用して値がソートされます。

  • MySQL では、GROUP BY の使用が、GROUP BY 句で指定されていないフィールドの選択を許可するように拡張されています。 クエリーから期待する結果が得られない場合は、セクション12.20「集計関数」にある GROUP BY の説明を参照してください。

  • GROUP BY では、WITH ROLLUP 修飾子が許可されます。 セクション12.20.2「GROUP BY 修飾子」を参照してください。

    以前は、WITH ROLLUP 修飾子を持つクエリーで ORDER BY を使用することはできませんでした。 この制限は、MySQL 8.0.12 の時点でなくなりました。 セクション12.20.2「GROUP BY 修飾子」を参照してください。

  • HAVING 句は、ほぼ最後 (項目がクライアントに送信される直前) に最適化なしで適用されます。 (LIMITHAVING のあとに適用されます。)

    SQL 標準では、HAVINGGROUP BY 句内のカラムか、または集約関数で使用されるカラムしか参照できません。 ただし、MySQL ではこの動作への拡張がサポートされており、HAVINGSELECT リスト内のカラムや外側サブクエリー内のカラムを参照することも許可されます。

    HAVING 句があいまいなカラムを参照している場合は、警告が発生します。 次のステートメントにある col2 は、エイリアスとカラム名の両方として使用されているため、あいまいです。

    SELECT COUNT(col1) AS col2 FROM t GROUP BY col2 HAVING col2 = 2;

    標準 SQL の動作の方が優先されるため、HAVING のカラム名が GROUP BY で使用されると同時に、出力カラムリスト内のエイリアスが指定されたカラムとしても使用されている場合は、GROUP BY カラム内のカラムが優先されます。

  • WHERE 句に含めるべき項目には HAVING を使用しないでください。 たとえば、次のように記述しないでください。

    SELECT col_name FROM tbl_name HAVING col_name > 0;

    代わりに、次のように記述してください。

    SELECT col_name FROM tbl_name WHERE col_name > 0;
  • HAVING 句は、WHERE 句が参照できない集約関数を参照できます。

    SELECT user, MAX(salary) FROM users
      GROUP BY user HAVING MAX(salary) > 10;

    (これは、一部の古いバージョンの MySQL では機能しませんでした。)

  • MySQL では、重複したカラム名が許可されます。 つまり、同じ名前を持つ複数の select_expr が存在できます。 これは、標準 SQL の拡張です。 MySQL では GROUP BYHAVINGselect_expr 値を参照することも許可されるため、これにより、あいまいさが発生する場合があります。

    SELECT 12 AS a, a FROM t GROUP BY a;

    このステートメントでは、どちらのカラムの名前も a です。 グループ化のために正しいカラムが使用されるようにするために、select_expr ごとに異なる名前を使用してください。

  • WINDOW 句が存在する場合は、ウィンドウ関数で参照できる名前付きウィンドウを定義します。 詳細は、セクション12.21.4「名前付きウィンドウ」を参照してください。

  • MySQL は、ORDER BY 句内の修飾されていないカラムまたはエイリアス参照を、まず select_expr 値、次に FROM 句内のテーブルのカラム内を検索することによって解決します。 GROUP BY または HAVING 句の場合は、select_expr 値内を検索する前に FROM 句を検索します。 (GROUP BYHAVING について、これは、ORDER BY) の場合と同じルールを使用していた MySQL 5.0 より前の動作とは異なります。

  • LIMIT 句を使用すると、SELECT ステートメントによって返される行数を制約できます。 LIMIT は 1 つまたは 2 つの数値引数を受け取ります。これは、どちらも負ではない整定数である必要があります。ただし、次の例外があります。

    • 準備済みステートメント内では、? プレースホルダマーカーを使用して LIMIT パラメータを指定できます。

    • ストアドプログラム内では、整数値のルーチンパラメータまたはローカル変数を使用して LIMIT パラメータを指定できます。

    引数が 2 つの場合、最初の引数は返す先頭行のオフセットを指定し、2 番目の引数は返す行の最大数を指定します。 最初の行のオフセットは (1 ではなく) 0 です。

    SELECT * FROM tbl LIMIT 5,10;  # Retrieve rows 6-15

    特定のオフセットから結果セットの最後までのすべての行を取得するために、2 番目のパラメータにある程度大きい数字を使用できます。 次のステートメントは、96 行目から最後の行までのすべての行を取得します。

    SELECT * FROM tbl LIMIT 95,18446744073709551615;

    引数が 1 つの場合、この値は、結果セットの先頭から返す行数を指定します。

    SELECT * FROM tbl LIMIT 5;     # Retrieve first 5 rows

    つまり、LIMIT row_countLIMIT 0, row_count と同等です。

    準備済みステートメントでは、プレースホルダを使用できます。 次のステートメントは、tbl テーブルから行を戻します:

    SET @a=1;
    PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?';
    EXECUTE STMT USING @a;

    次のステートメントは、tbl テーブルから秒から 6 行目を戻します:

    SET @skip=1; SET @numrows=5;
    PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?, ?';
    EXECUTE STMT USING @skip, @numrows;

    PostgreSQL との互換性のために、MySQL は LIMIT row_count OFFSET offset 構文もサポートしています。

    LIMIT がカッコで囲まれたクエリー式内で発生し、外部クエリーにも適用される場合、結果は未定義であり、将来のバージョンの MySQL で変更される可能性があります。

  • SELECTSELECT ... INTO 形式を使用すると、クエリー結果をファイルに書き込んだり、変数に格納したりできます。 詳細は、セクション13.2.10.1「SELECT ... INTO ステートメント」を参照してください。

  • FOR UPDATE をページロックまたは行ロックを使用するストレージエンジンとともに使用する場合、クエリーによって検査される行は、現在のトランザクションが終了するまで書き込みロックされます。

    CREATE TABLE new_table SELECT ... FROM old_table ... などのステートメントで SELECT の一部として FOR UPDATE を使用することはできません。 (それを行おうとすると、このステートメントはエラー Can't update table 'old_table' while 'new_table' is being createdで拒否されます。)

    FOR SHARE および LOCK IN SHARE MODE では、他のトランザクションが調査された行を読み取ることはできるが、更新または削除することはできない共有ロックが設定されます。 FOR SHARELOCK IN SHARE MODE は同等です。 ただし、FOR UPDATE と同様に、FOR SHARENOWAITSKIP LOCKED および OF tbl_name オプションをサポートしています。 FOR SHARELOCK IN SHARE MODE の代替機能ですが、LOCK IN SHARE MODE は下位互換性のために引き続き使用できます。

    NOWAIT では、FOR UPDATE または FOR SHARE クエリーがすぐに実行され、別のトランザクションによってロックが保持されているために行ロックを取得できない場合はエラーが返されます。

    SKIP LOCKED では、別のトランザクションによってロックされている結果セットから行を除外して、FOR UPDATE または FOR SHARE クエリーがただちに実行されます。

    NOWAIT および SKIP LOCKED オプションは、ステートメントベースレプリケーションでは安全ではありません。

    注記

    ロックされた行をスキップするクエリーは、データの一貫性のないビューを返します。 したがって、SKIP LOCKED は一般的なトランザクション作業には適していません。 ただし、複数のセッションが同じキューに類似したテーブルにアクセスする場合、ロックの競合を回避するために使用できます。

    OF tbl_name は、FOR UPDATE および FOR SHARE クエリーを名前付きテーブルに適用します。 例:

    SELECT * FROM t1, t2 FOR SHARE OF t1 FOR UPDATE OF t2;

    OF tbl_name を省略すると、クエリーブロックによって参照されるすべてのテーブルがロックされます。 したがって、別のロック句と組み合せて OF tbl_name なしでロック句を使用すると、エラーが返されます。 複数のロック句で同じテーブルを指定すると、エラーが返されます。 エイリアスが SELECT ステートメントでテーブル名として指定されている場合、ロック句ではエイリアスのみを使用できます。 SELECT ステートメントでエイリアスが明示的に指定されていない場合、ロック句では実際のテーブル名のみを指定できます。

    FOR UPDATE および FOR SHARE の詳細は、セクション15.7.2.4「読取りのロック」 を参照してください。 NOWAIT および SKIP LOCKED オプションの詳細は、NOWAIT および SKIP LOCKED による読取り同時実行性のロック を参照してください。

SELECT キーワードの後に、ステートメントの操作に影響を与える多数の修飾子を使用できます。 HIGH_PRIORITYSTRAIGHT_JOIN および SQL_以降の修飾子は、標準 SQL に対する MySQL の拡張機能です。

  • ALL 修飾子および DISTINCT 修飾子は、重複する行を戻すかどうかを指定します。 ALL (デフォルト) は、重複を含め、一致するすべての行を返すように指定します。 DISTINCT は、重複した行の結果セットからの削除を指定します。 両方の修飾子を指定するとエラーになります。 DISTINCTROWDISTINCT のシノニムです。

    MySQL 8.0.12 以降では、WITH ROLLUP も使用するクエリーで DISTINCT を使用できます。 (Bug #87450、Bug #26640100)

  • HIGH_PRIORITY では、テーブルを更新するステートメントよりも SELECT の優先度が高くなります。 これは、非常に高速であり、かつただちに実行する必要のあるクエリーにのみ使用するようにしてください。 テーブルが読み取りに対してロックされている間に発行された SELECT HIGH_PRIORITY クエリーは、そのテーブルが未使用になるのを待機している更新ステートメントが存在する場合でも実行されます。 これは、テーブルレベルロックのみを使用するストレージエンジン (MyISAMMEMORY、および MERGE) にのみ影響を与えます。

    HIGH_PRIORITY を、UNION の一部である SELECT ステートメントで使用することはできません。

  • STRAIGHT_JOIN では、オプティマイザによって、FROM 句にリストされている順序でテーブルが結合されます。 オプティマイザがテーブルを最適でない順序で結合する場合は、これを使用してクエリーを高速化できます。 STRAIGHT_JOIN はまた、table_references リストでも使用できます。 セクション13.2.10.2「JOIN 句」を参照してください。

    STRAIGHT_JOIN は、オプティマイザが const または system テーブルとして扱うテーブルには適用されません。 このようなテーブルは単一行を生成し、クエリー実行の最適化フェーズ中に読み取られます。また、そのカラムへの参照は、クエリー実行が続行される前に適切なカラム値で置き換えられます。 これらのテーブルは、EXPLAIN によって表示されるクエリー計画の最初に表示されます。 「セクション8.8.1「EXPLAIN によるクエリーの最適化」」を参照してください。 この例外は、外部結合の NULL で補完された側で使用されている const テーブルまたは system テーブル (つまり、LEFT JOIN の右側のテーブルまたは RIGHT JOIN の左側のテーブル) には適用されない可能性があります。

  • SQL_BIG_RESULT または SQL_SMALL_RESULTGROUP BY または DISTINCT とともに使用して、結果セットに多数の行があるか、それぞれ小さいことをオプティマイザに伝えることができます。 SQL_BIG_RESULT の場合、MySQL ではディスクベースの一時テーブルが直接使用され (作成されている場合)、GROUP BY 要素のキーを使用した一時テーブルよりソートが優先されます。 SQL_SMALL_RESULT の場合、MySQL では、ソートを使用するかわりにインメモリー一時テーブルを使用して結果テーブルを格納します。 これは、通常は必要ないはずです。

  • SQL_BUFFER_RESULT では、結果が強制的に一時テーブルに格納されます。 これは、MySQL がテーブルロックを早期に解放する場合や、結果セットをクライアントに送信するのに長い時間がかかる場合に役立ちます。 この修飾子は、トップレベルの SELECT ステートメントにのみ使用でき、サブクエリーや UNION の後には使用できません。

  • SQL_CALC_FOUND_ROWS は、LIMIT 句に関係なく、結果セットに存在する行数を計算するように MySQL に指示します。 そのあと、行数は SELECT FOUND_ROWS() を使用して取得できます。 セクション12.16「情報関数」を参照してください。

    注記

    SQL_CALC_FOUND_ROWS クエリー修飾子および付随する FOUND_ROWS() 関数は、MySQL 8.0.17 で非推奨になりました。これらは、MySQL の将来のバージョンで削除される予定です。 代替戦略の詳細は、FOUND_ROWS() の説明を参照してください。

  • SQL_CACHE および SQL_NO_CACHE 修飾子は、MySQL 8.0 より前のクエリーキャッシュで使用されていました。 クエリーキャッシュは MySQL 8.0 で削除されました。 SQL_CACHE 修飾子も削除されました。 SQL_NO_CACHE は非推奨であり、効果はありません。将来の MySQL リリースで削除される予定です。


関連キーワード:  ステートメント, テーブル, 参照, カラム, FROM, CREATE, TABLE, クエリー, ロック, セクション