すべてのプロダクト
Search
ドキュメントセンター

MaxCompute:SELECT構文

最終更新日:Dec 09, 2024

MaxComputeでは、SELECTステートメントを使用してデータをクエリできます。 このトピックでは、MaxComputeのSELECTステートメントの構文について説明します。 このトピックでは、SELECTステートメントを使用して、ネストされたクエリ、並べ替え、グループごとのクエリなどの操作を実行する方法についても説明します。

SELECTステートメントを実行する前に、ターゲットテーブルでSelect権限が付与されていることを確認してください。 詳細は、「MaxCompute権限」をご参照ください。

次のプラットフォームでステートメントを実行できます。

概要

SELECT文は、指定された条件を満たすデータをテーブルから照会するために使用されます。 次の表に、さまざまなシナリオで実行できるクエリ操作を示します。

クエリ操作

説明

サブクエリ

クエリの結果に基づいてさらにクエリを実行できます。

INTERSECT, UNION, and EXCEPT

2つのデータセットの共通部分、和集合、または補足セットを取得できます。

JOIN

JOIN操作を実行してテーブルを結合し、結合条件とクエリ条件を満たすデータを取得できます。

SEMI JOIN

右のテーブルを使用して左のテーブルのデータをフィルタリングし、左のテーブルにのみ表示されるデータを取得できます。

MAPJOIN のヒント

1つの大きなテーブルと1つ以上の小さなテーブルに対してJOIN操作を実行するときに、SELECTステートメントでMAPJOINヒントを明示的に指定できます。 これにより、クエリのパフォーマンスが向上します。

SKEWJOINのヒント

結合する2つのテーブルにホットキー値が含まれている場合、ロングテールの問題が発生する可能性があります。 2つのテーブルからホットキー値を抽出し、ホットキー値の結合結果と非ホットキー値の結合結果を別々に計算してから、計算されたデータを結合することができます。

側面図

LATERAL VIEWとユーザー定義のテーブル値関数 (UDTF) を使用して、1行のデータを複数の行に分割できます。

グループ化セット

複数のディメンションからのデータを集計および分析できます。

SELECT TRANSFORM

指定した子プロセスを開始し、標準入力を使用して必要な形式でデータを入力できます。 次に、子プロセスの標準出力を解析して出力データを取得できます。

Split Size Hint

分割サイズを変更して、サブタスクの並列処理を制御できます。

Time travelクエリとincrementalクエリ

MaxComputeでは、トランザクションテーブル2.0のテーブルに対して、タイムトラベルクエリと増分クエリを実行できます。

  • time travelのクエリを実行する場合は、過去の時点または過去のバージョンのソーステーブルのスナップショットに基づいて、履歴データをクエリできます。

  • incremental クエリを実行すると、履歴期間内、またはソーステーブルの2つのバージョン間の履歴増分データをクエリできます。

制限事項

  • SELECTステートメントを実行した後、最大10,000行の結果を表示できます。 返される結果のサイズは10 MB未満である必要があります。 この制限は、SELECT句には適用されません。 SELECT句は、上位層からのクエリに応答してすべての結果を返します。

  • SELECT文を実行してパーティションテーブルのデータを照会する場合、テーブルに対して完全なテーブルスキャンを実行することはできません。

    プロジェクトが2018年1月10日の20:00:00以降に作成された場合、プロジェクト内のパーティションテーブルに対して完全なテーブルスキャンを実行することはできません。 この制限は、SELECTステートメントを実行してテーブルからデータを照会する場合に適用されます。 パーティションテーブルのデータをクエリするには、スキャンするパーティションを指定する必要があります。 これにより、不要なI/Oが減り、コンピューティングリソースが節約されます。 これにより、従量課金方法を使用すると、コンピューティングコストも削減されます。

    パーティションテーブルでフルテーブルスキャンを実行するには、フルテーブルスキャンに使用されるsql文の前にset odps. SQL. allow.fullscan=true; コマンドを追加します。 次に、追加したコマンドをSQL文でコミットして実行します。 たとえば、sale_detailパーティションテーブルに対してテーブル全体のスキャンを実行する場合は、次のステートメントを実行します。

    set odps.sql.allow.fullscan=true;
    select * from sale_detail;
  • クラスター化されたテーブルをクエリする場合は、1つのテーブルでスキャンできるパーティションの数が400以下の場合にのみ、SELECTステートメントを実行してバケットのプルーニングを実行できます。 バケットのプルーニングが有効にならない場合、スキャンされるデータレコードの数が増加します。 従量課金方法を使用し、バケットのプルーニングが有効にならない場合、コストが増加します。 サブスクリプションの課金方法を使用し、バケットのプルーニングが有効にならない場合、SQLコンピューティングのパフォーマンスが低下します。

構文

[with <cte>[, ...] ]
select [all | distinct] <select_expr>[, <except_expr>][, <replace_expr>] ...
       from <table_reference>
       [where <where_condition>]
       [group by {<col_list>|rollup(<col_list>)}]
       [having <having_condition>]
       [window <window_clause>]
       [order by <order_condition>]
       [distribute by <distribute_condition> [sort by <sort_condition>]|[ cluster by <cluster_condition>] ]
       [limit <number>]

SELECTステートメントで句を実行するシーケンスの詳細については、「SELECTステートメントで句を実行するシーケンス」をご参照ください。

サンプルデータ

このトピックでは、サンプルソースデータとサンプルステートメントを提供し、ソースデータの準備方法を示します。 次のサンプルステートメントは、sale_detailテーブルを作成し、このテーブルにデータを挿入する方法を示しています。

-- Create a partitioned table named sale_detail. 
create table if not exists sale_detail
(
shop_name     string,
customer_id   string,
total_price   double
)
partitioned by (sale_date string, region string);

-- Add partitions to the sale_detail table. 
alter table sale_detail add partition (sale_date='2013', region='china');

-- Insert data into the sale_detail table. 
insert into sale_detail partition (sale_date='2013', region='china') values ('s1','c1',100.1),('s2','c2',100.2),('s3','c3',100.3);

sale_detailテーブルのデータを照会します。 例:

select * from sale_detail;
-- The following result is returned: 
+------------+------------+------------+------------+------------+
| shop_name  | price      | customer   | sale_date  | region     |
+------------+------------+------------+------------+------------+
| s1         | 100.1      | c1         | 2013       | china      |
| s2         | 100.2      | c2         | 2013       | china      |
| s3         | 100.3      | c3         | 2013       | china      |
+------------+------------+------------+------------+------------+

WITH句 (CTE)

WITH句はオプションです。 WITH句には、1つ以上の共通テーブル式 (CTE) が含まれます。 CTEは、ランタイム環境で一時テーブルとして使用されます。 後続のクエリで一時テーブルを参照できます。 CTEを使用するときは、次のルールに従う必要があります。

  • CTEの名前は、WITH句で一意である必要があります。

  • WITH句で定義されているCTEは、同じWITH句で定義されている他のCTEによってのみ参照できます。

    たとえば、AはWITH句の最初のCTEであり、Bは同じWITH句の2番目のCTEです。

    • AがAを参照する場合、参照は無効である。 CTEの不正な使用:

      with 
      A as (select 1 from A) 
      select * from A;
    • AがBを参照し、BがAを参照する場合、参照は無効である。 循環参照には対応していません。 CTEの不正な使用:

      with 
      A as (select * from B ), 
      B as (select * from A ) 
      select * from B;

正しい使用法のサンプルステートメント:

with 
A as (select 1 as C),
B as (select * from A) 
select * from B;

次の応答が返されます。

+---+
| c |
+---+
| 1 |
+---+

列式 (select_expr)

select_exprは必須です。 select_exprの形式は、col1_name, col2_name, column expression,... です。 この形式は、クエリする共通列またはパーティションキー列、またはデータのクエリに使用する正規表現を示します。 select_exprを使用する場合は、次のルールに従う必要があります。

  • データを読み取る列の名前を指定します。

    次のステートメントは、sale_detailテーブルからshopp_name列のデータを読み取ります。 例:

    select shop_name from sale_detail;

    次の応答が返されます。

    +------------+
    | shop_name  |
    +------------+
    | s1         |
    | s2         |
    | s3         |
    +------------+
  • すべての列を表すには、アスタリスク (*) を使用します。 where_conditionにアスタリスク (*) を使用して、フィルター条件を指定することもできます。

    • 次のステートメントは、sale_detailテーブルのすべての列のデータを照会します。 例:

      -- Enable a full table scan only for the current session. 
      set odps.sql.allow.fullscan=true;
      select * from sale_detail;

      次の応答が返されます。

      +------------+-------------+-------------+------------+------------+
      | shop_name  | customer_id | total_price | sale_date  | region     |
      +------------+-------------+-------------+------------+------------+
      | s1         | c1          | 100.1       | 2013       | china      |
      | s2         | c2          | 100.2       | 2013       | china      |
      | s3         | c3          | 100.3       | 2013       | china      |
      +------------+-------------+-------------+------------+------------+
    • 次のステートメントでは、アスタリスク (*) とwhere_conditionを使用してフィルター条件を指定します。 例:

      select * from sale_detail where shop_name='s1';

      次の応答が返されます。

      +------------+-------------+-------------+------------+------------+
      | shop_name  | customer_id | total_price | sale_date  | region     |
      +------------+-------------+-------------+------------+------------+
      | s1         | c1          | 100.1       | 2013       | china      |
      +------------+-------------+-------------+------------+------------+
  • 正規表現を使用します。

    • 次のステートメントは、sale_detailテーブルの名前がshで始まるすべての列のデータを照会します。 例:

      select `sh.*` from sale_detail;

      次の応答が返されます。

      +------------+
      | shop_name  |
      +------------+
      | s1         |
      | s2         |
      | s3         |
      +------------+
    • 次のステートメントは、sale_detailテーブルのshop_name以外のすべての列のデータを照会します。 例:

      select `(shop_name)?+.+` from sale_detail;

      次の応答が返されます。

      +-------------+-------------+------------+------------+
      | customer_id | total_price | sale_date  | region     |
      +-------------+-------------+------------+------------+
      | c1          | 100.1       | 2013       | china      |
      | c2          | 100.2       | 2013       | china      |
      | c3          | 100.3       | 2013       | china      |
      +-------------+-------------+------------+------------+
    • 次のステートメントは、sale_detailテーブルのshop_nameおよびcustomer_idの列を除くすべての列のデータを照会します。 例:

      select `(shop_name|customer_id)?+.+` from sale_detail;

      次の応答が返されます。

      +-------------+------------+------------+
      | total_price | sale_date  | region     |
      +-------------+------------+------------+
      | 100.1       | 2013       | china      |
      | 100.2       | 2013       | china      |
      | 100.3       | 2013       | china      |
      +-------------+------------+------------+
    • 次のステートメントは、sale_detailテーブルの名前がtで始まる列を除くすべての列のデータを照会します。 例:

      select `(t.*)?+.+` from sale_detail;

      次の応答が返されます。

      +------------+-------------+------------+------------+
      | shop_name  | customer_id | sale_date  | region     |
      +------------+-------------+------------+------------+
      | s1         | c1          | 2013       | china      |
      | s2         | c2          | 2013       | china      |
      | s3         | c3          | 2013       | china      |
      +------------+-------------+------------+------------+
      説明

      col2の名前がcol1の名前のプレフィックスであり、複数の列を除外する場合は、col1の名前がcol2の名前の前に配置されていることを確認する必要があります。 長い列名は短い列名の前に配置されます。 たとえば、パーティション分割テーブルの2つのパーティションを照会する必要はありません。 一方のパーティションはds、もう一方のパーティションはdshhです。 dsパーティションの名前は、dshhパーティションの名前のプレフィックスです。 したがって、select '(dshhds)?+.+' from t; は正しいが、select '(dsdshh)?+' from t; は正しくない。

  • 列の名前の前にDISTINCTを使用して、列から重複する値を除外し、異なる値のみを返します。 列の名前の前にALLを使用すると、重複する値を含む列のすべての値が返されます。 DISTINCTを使用しない場合は、ALLが使用されます。

    • 次のステートメントは、sale_detailテーブルからregion列のデータを照会し、1つの個別の値のみを返します。 例:

      select distinct region from sale_detail;

      次の応答が返されます。

      +------------+
      | region     |
      +------------+
      | china      |
      +------------+
    • 次のステートメントでは、DISTINCTオプションの後に複数の列を指定します。 DISTINCTオプションは、単一の列ではなく、指定されたすべての列に対して有効になります。 例:

      select distinct region, sale_date from sale_detail;

      次の応答が返されます。

      +------------+------------+
      | region     | sale_date  |
      +------------+------------+
      | china      | 2013       |
      +------------+------------+
    • 次のステートメントでは、DISTINCTはウィンドウ関数と一緒に使用されます。 DISTINCTは、ウィンドウ関数の計算結果を重複排除するために使用されます。 例:

      set odps.sql.allow.fullscan=true;
      select distinct sale_date, row_number() over (partition by customer_id order by total_price) as rn from sale_detail;

      次の応答が返されます。

      +-----------+------------+
      | sale_date | rn         |
      +-----------+------------+
      | 2013      | 1          |
      +-----------+------------+

      次のステートメントでは、DISTINCTGROUP BYと共に使用できません。 たとえば、次のステートメントを実行すると、エラーが返されます。

      select distinct shop_name from sale_detail group by shop_name;
      -- The error message "GROUP BY cannot be used with SELECT DISTINCT" is returned.

列の除外式 (except_expr)

except_exprはオプションです。 except_exprexcept(col1_name, col2_name, ...) 形式です。 except_exprを使用すると、テーブル内のほとんどの列からデータを読み取り、テーブル内の少数の列からデータを除外できます。 たとえば、select * except(col1_name, col2_name, ...) from ...; 文を実行して、col1列とcol2列を除くすべての列からデータを読み取ることができます。

例:

-- Read data from all columns, except the region column, in the sale_detail table. 
select * except(region) from sale_detail;

次の応答が返されます。

+-----------+-------------+-------------+-----------+
| shop_name | customer_id | total_price | sale_date |
+-----------+-------------+-------------+-----------+
| s1        | c1          | 100.1       | 2013      |
| s2        | c2          | 100.2       | 2013      |
| s3        | c3          | 100.3       | 2013      |
+-----------+-------------+-------------+-----------+

列変更式 (replace_expr)

replace_exprはオプションです。 replace_exprは、replace(exp1 [as] col1_name, exp2 [as] col2_name, ...) 形式です。 replace_exprを使用すると、テーブル内のほとんどの列からデータを読み取り、テーブル内の少数の列のデータを変更できます。 たとえば、select * replace(exp1 as col1_name, exp2 as col2_name, ...) from ...; ステートメントを実行して、col1列のデータをexp1の計算結果に置き換え、col2列のデータをexp2の計算結果に置き換えることができます。

例:

-- Read data from the sale_detail table and modify the data in the total_price and region columns. 
select * replace(total_price+100 as total_price, 'shanghai' as region) from sale_detail;

次の応答が返されます。

+-----------+-------------+-------------+-----------+--------+
| shop_name | customer_id | total_price | sale_date | region |
+-----------+-------------+-------------+-----------+--------+
| s1        | c1          | 200.1       | 2013      | shanghai |
| s2        | c2          | 200.2       | 2013      | shanghai |
| s3        | c3          | 200.3       | 2013      | shanghai |
+-----------+-------------+-------------+-----------+--------+

宛先テーブル情報 (table_reference)

table_referenceが必要です。 table_referenceは、クエリするテーブルを指定します。 table_referenceを使用する場合は、次のルールに従う必要があります。

  • 宛先テーブルの名前を指定します。 例:

    select customer_id from sale_detail;

    次の応答が返されます。

    +-------------+
    | customer_id |
    +-------------+
    | c1          |
    | c2          |
    | c3          |
    +-------------+
  • ネストされたサブクエリを使用します。 例:

    select * from (select region,sale_date from sale_detail) t where region = 'china';

    次の応答が返されます。

    +------------+------------+
    | region     | sale_date  |
    +------------+------------+
    | china      | 2013       |
    | china      | 2013       |
    | china      | 2013       |
    +------------+------------+

WHERE句 (where_condition)

where_conditionはオプションです。 where_conditionはフィルター条件を指定します。 where_conditionがパーティションテーブルに使用される場合、列の剪定を実行できます。 where_conditionを使用する場合は、次のルールに従う必要があります。

  • リレーショナル演算子でwhere_conditionを使用して、指定された条件を満たすデータを取得します。 関係演算子は次のとおりです。

    • ><=>=<=<>

    • LIKERLIKE

    • インイン

    • BETWEEN…AND

    詳細については、「リレーショナル演算子」をご参照ください。

    次のステートメントは、where_conditionでスキャンするパーティションを指定します。 これにより、テーブル全体のスキャンが防止されます。 例:

    select * 
    from sale_detail
    where sale_date >= '2008' and sale_date <= '2014';
    -- The preceding statement is equivalent to the following statement: 
    select * 
    from sale_detail 
    where sale_date between '2008' and '2014';

    次の応答が返されます。

    +------------+-------------+-------------+------------+------------+
    | shop_name  | customer_id | total_price | sale_date  | region     |
    +------------+-------------+-------------+------------+------------+
    | s1         | c1          | 100.1       | 2013       | china      |
    | s2         | c2          | 100.2       | 2013       | china      |
    | s3         | c3          | 100.3       | 2013       | china      |
    +------------+-------------+-------------+------------+------------+
    説明

    EXPLAINステートメントを実行して、パーティションプルーニングが有効かどうかを確認できます。 一般的なユーザー定義関数 (UDF) またはJOINのパーティション条件設定により、パーティションプルーニングが失敗する場合があります。 詳細については、「パーティションプルーニングが有効かどうかの確認」をご参照ください。

  • UDFベースのパーティションプルーニングを使用します。 UDFを使用する場合、MaxComputeはUDFを小さなジョブとして実行し、これらのジョブの結果をパーティションにバックフィルします。

    • 実装方法

      • UDFを記述するときに、UDFクラスに注釈を追加します。

        @com.aliyun.odps.udf.annotation.UdfProperty(isDeterministic=true)
        説明

        UDFアノテーションcom.aliyun.odps.udf.annotation.UdfPropertyは、odps-sdk-udf.jarファイルで定義されています。 このアノテーションを使用するには、参照先のodps-sdk-udfのバージョンを0.30.X以降に更新する必要があります。

      • 実行するSQL文の前に、set odps.sql.udf.ppr.de terministic = true; を追加します。 次に、SQL文のすべてのUDFがdeterministicUDFと見なされます。 上記のSETコマンドは、ジョブの結果でパーティションをバックフィルします。 ジョブの結果で最大1,000個のパーティションをバックフィルできます。 UDFクラスにアノテーションを追加すると、1,000を超えるパーティションがバックフィルされていることを示すエラーが返される場合があります。 このエラーを無視するには、set odps.sql.udf.ppr. To. subquery = false; コマンドを実行します。 このコマンドを実行すると、UDFベースのパーティションプルーニングは無効になります。

    • 注意事項

      UDFを使用してパーティションプルーニングを実行する場合は、テーブルのクエリに使用するWHERE句にUDFを配置する必要があります。 UDFベースのパーティションプルーニングは、WHERE句にUDFを配置した場合にのみ有効になります。

      • 正しい使用法のサンプルステートメント:

        --Place a UDF in the WHERE clause that is used to query the source table.
        select key, value from srcp where udf(ds) = 'xx';
      • 誤った使用法のサンプルステートメント:

        --Place a UDF after the ON condition in the JOIN clause. UDF-based partition pruning does not take effect.
        select A.c1, A.c2 from srcp1 A  join srcp2  B on A.c1 = B.c1 and udf(A.ds) ='xx';
  • 列式 (select_expr) では、列エイリアスに名前が変更された列が関数を使用している場合、列エイリアスはWHERE句で参照できません。 誤ったサンプル文:

    select  task_name
            ,inst_id
            ,settings
            ,GET_JSON_OBJECT(settings, '$.SKYNET_ID') as skynet_id
            ,GET_JSON_OBJECT(settings, '$.SKYNET_NODENAME') as user_agent
    from    Information_Schema.TASKS_HISTORY
    where   ds = '20211215' and skynet_id is not null
    limit 10;

GROUP BY (col_list)

GROUP BYはオプションです。 ほとんどの場合、GROUP BY集計関数とともに使用され、指定された共通列、パーティションキー列、または正規表現に基づいて列をグループ化します。 GROUP BYを使用する場合は、次のルールに従う必要があります。

  • GROUP BYSELECTよりも優先されます。 したがって、GROUP BYの列は、SELECTの入力テーブルの列名またはSELECTの入力テーブルの列で構成される式で指定できます。 GROUP BYを使用する場合は、次の点に注意してください。

    • GROUP BYの列が正規表現で指定されている場合は、完全な表現を使用する必要があります。

    • SELECTステートメントで集計関数を使用しない列は、GROUP BYで指定する必要があります。

    例:

    • 次のステートメントは、テーブルデータを列名領域でグループ化します。 この場合、データはリージョン列の値に基づいてグループ化されます。 サンプル文:

      select region from sale_detail group by region;

      次の応答が返されます。

      +------------+
      | region     |
      +------------+
      | china      |
      +------------+
    • 次のステートメントは、リージョン列の値に基づいてテーブルデータをグループ化し、各グループの合計売上を返します。 例:

      select sum(total_price) from sale_detail group by region;

      次の応答が返されます。

      +------------+
      | _c0        |
      +------------+
      | 300.6      |
      +------------+
    • 次のステートメントは、リージョン列の値に基づいてテーブルデータをグループ化し、各グループの個別の値と総売上高を返します。 例:

      select region, sum (total_price) from sale_detail group by region;

      次の応答が返されます。

      +------------+------------+
      | region     | _c1        |
      +------------+------------+
      | china      | 300.6      |
      +------------+------------+
    • 次のステートメントは、SELECTステートメントの出力列のエイリアスに基づいてテーブルデータをグループ化します。 例:

      select region as r from sale_detail group by r;
      -- The preceding statement is equivalent to the following statement: 
      select region as r from sale_detail group by region;

      次の応答が返されます。

      +------------+
      | r          |
      +------------+
      | china      |
      +------------+
    • 次の文は、列式に基づいてテーブルデータをグループ化します。 例:

      select 2 + total_price as r from sale_detail group by 2 + total_price;

      次の応答が返されます。

      +------------+
      | r          |
      +------------+
      | 102.1      |
      | 102.2      |
      | 102.3      |
      +------------+
    • SELECTステートメントの一部の列が集計関数を使用しない場合、これらの列はGROUP BYで指定する必要があります。 それ以外の場合は、エラーが返されます。 誤った使用法のサンプルステートメント:

      select region, total_price from sale_detail group by region;

      正しい使用法のサンプルステートメント:

      select region, total_price from sale_detail group by region, total_price;

      次の応答が返されます。

      +------------+-------------+
      | region     | total_price |
      +------------+-------------+
      | china      | 100.1       |
      | china      | 100.2       |
      | china      | 100.3       |
      +------------+-------------+
  • SELECTステートメントの前にset hive.groupby.position.alias=true; コマンドを追加した場合、GROUP BY句の整数定数はSELECTステートメントの列番号と見なされます。 例:

    -- Run this command with the following SELECT statement. 
    set odps.sql.groupby.position.alias=true;
    -- 1 indicates the region column, which is the first column read by the following SELECT statement. This statement groups table data based on the values of the region column and returns distinct values of the region column and total sales of each group. 
    select region, sum(total_price) from sale_detail group by 1;

    次の応答が返されます。

    +------------+------------+
    | region     | _c1        |
    +------------+------------+
    | china      | 300.6      |
    +------------+------------+

HAVING句 (having_condition)

having_conditionはオプションです。 ほとんどの場合、having_conditionは集計関数で使用され、データをフィルタリングします。 例:

-- Insert data into the sale_detail table to display the data rendering effect. 
insert into sale_detail partition (sale_date='2014', region='shanghai') values ('null','c5',null),('s6','c6',100.4),('s7','c7',100.5);
-- Use having_condition with aggregate functions to filter data. 
select region,sum(total_price) from sale_detail 
group by region 
having sum(total_price)<305;

次の応答が返されます。

+------------+------------+
| region     | _c1        |
+------------+------------+
| china      | 300.6      |
| shanghai   | 200.9      |
+------------+------------+

ORDER BY (order_condition)

order_conditionはオプションです。 ORDER BYは、指定された共通列またはパーティションキー列に基づいてすべてのデータレコードをソートするために使用されます。 ORDER BYを使用して、指定した定数に基づいてすべてのデータレコードをソートすることもできます。 ORDER BYを使用する場合は、次のルールに従う必要があります。

  • デフォルトでは、データは昇順でソートされます。 データを降順でソートする場合は、DESCキーワードが必要です。

  • デフォルトでは、ORDER Byの後にLIMIT <number> が続き、出力に表示されるデータ行の数が制限されます。 ORDER BYの後にLIMIT <number> が続かない場合、エラーが返されます。 このlimitを回避することもできます。 詳細は、「LIMIT」をご参照ください。

    • 次のステートメントは、sale_detailテーブルからデータを照会し、total_price列の値に基づいてデータレコードを昇順に並べ替え、最初の2つのレコードを表示します。 例:

      select * from sale_detail order by total_price limit 2;

      次の応答が返されます。

      +------------+-------------+-------------+------------+------------+
      | shop_name  | customer_id | total_price | sale_date  | region     |
      +------------+-------------+-------------+------------+------------+
      | s1         | c1          | 100.1       | 2013       | china      |
      | s2         | c2          | 100.2       | 2013       | china      |
      +------------+-------------+-------------+------------+------------+
    • 次のステートメントは、sale_detailテーブルからデータを照会し、total_price列の値に基づいてデータレコードを降順に並べ替え、最初の2つのレコードを表示します。 例:

      select * from sale_detail order by total_price desc limit 2;

      次の応答が返されます。

      +------------+-------------+-------------+------------+------------+
      | shop_name  | customer_id | total_price | sale_date  | region     |
      +------------+-------------+-------------+------------+------------+
      | s3         | c3          | 100.3       | 2013       | china      |
      | s2         | c2          | 100.2       | 2013       | china      |
      +------------+-------------+-------------+------------+------------+
  • NULLは、ORDER BYを使用してデータをソートする場合の最小値です。 これはMySQLにも当てはまります。 ただし、Oracleではそうではありません。

    次のステートメントは、sale_detailテーブルからデータを照会し、total_price列の値に基づいてデータレコードを昇順に並べ替え、最初の2つのレコードを表示します。 例:

    select * from sale_detail order by total_price limit 2;

    次の応答が返されます。

    +------------+-------------+-------------+------------+------------+
    | shop_name  | customer_id | total_price | sale_date  | region     |
    +------------+-------------+-------------+------------+------------+
    | s1         | c1          | 100.1       | 2013       | china      |
    | s2         | c2          | 100.2       | 2013       | china      |
    +------------+-------------+-------------+------------+------------+
  • ORDER BYの後には、SELECTステートメントの出力列のエイリアスが続きます。 SELECTステートメントの出力列のエイリアスを指定しない場合、この列の名前がこの列のエイリアスとして使用されます。

    次のステートメントは、ORDER BYの後に出力列のエイリアスを追加します。 例:

    select total_price as t from sale_detail order by total_price limit 3;
    -- The preceding statement is equivalent to the following statement: 
    select total_price as t from sale_detail order by t limit 3;

    次の応答が返されます。

    +------------+
    | t          |
    +------------+
    | 100.1      |
    | 100.2      |
    | 100.3      |
    +------------+
  • SELECTステートメントの前にset hive.orderby.position.alias=true; コマンドを追加した場合、ORDER BY句の整数定数はSELECTステートメントの列番号と見なされます。 例:

    -- Run this command with the following SELECT statement. 
    set odps.sql.orderby.position.alias=true;
    select * from sale_detail order by 3 limit 3;

    次の応答が返されます。

    +------------+-------------+-------------+------------+------------+
    | shop_name  | customer_id | total_price | sale_date  | region     |
    +------------+-------------+-------------+------------+------------+
    | s1         | c1          | 100.1       | 2013       | china      |
    | s2         | c2          | 100.2       | 2013       | china      |
    | s3         | c3          | 100.3       | 2013       | china      |
    +------------+-------------+-------------+------------+------------+
  • OFFSET句は、ORDER BY...LIMIT句とともに使用して、スキップする行数を指定できます。 形式はORDER BY...LIMIT m OFFSET nで、ORDER BY...LIMIT n, mと省略できます。 LIMIT mは、m行のデータが返されることを指定します。 OFFSET nは、データが返される前にn行をスキップすることを指定します。 行をスキップしたくない場合は、実行するステートメントでOFFSET 0を使用できます。 OFFSET句を指定せずにステートメントを実行することもできます。

    次のステートメントは、total_price列の値に基づいてsale_detailテーブルのデータを昇順でソートし、3行目から始まる3行のデータを表示します。 例:

    select customer_id,total_price from sale_detail order by total_price limit 3 offset 2;
    -- The preceding statement is equivalent to the following statement: 
    select customer_id,total_price from sale_detail order by total_price limit 2, 3;

    次の応答が返されます。

    +-------------+-------------+
    | customer_id | total_price |
    +-------------+-------------+
    | c3          | 100.3       |
    +-------------+-------------+

    照会されたデータには3行のデータしか含まれません。 この場合、3行目のみが返されます。

  • 範囲クラスタリングは、グローバルソートの高速化にも使用できます。 ORDER BYが使用される一般的なシナリオでは、すべてのソート済みデータが同じインスタンスに分散され、グローバルなソートが保証されます。 ただし、これらのシナリオでは同時処理を完全に利用できません。 範囲クラスタリングのパーティショニングステップを使用して、同時グローバルソートを実装できます。 グローバルソートを実行する場合は、データをサンプリングして範囲に分割し、各範囲のデータを並列にソートしてから、グローバルソートの結果を取得する必要があります。 詳細については、「グローバルソートの高速化」をご参照ください。

ハッシュパーティションによる分配 (distribute_condition)

distribute_conditionはオプションです。 DISTRIBUTE BYは、特定の列の値に基づいてデータに対してハッシュ分割を実行するために使用されます。

DISTRIBUTE BYは、マッパーの出力がリデューサー間でどのように分配されるかを制御します。 同じデータが異なるレデューサーに配信されないようにするには、DISTRIBUTE BYを使用します。 これにより、同じデータグループが同じリデューサーに確実に配信されます。

SELECTステートメントの出力列のエイリアスを指定する必要があります。 SELECT文を実行して列のデータを照会し、この列のエイリアスが指定されていない場合、列名はエイリアスとして使用されます。 例:

-- The following statement queries the values of the region column from the sale_detail table and performs hash partitioning on data based on the values of the region column. 
select region from sale_detail distribute by region;
-- The preceding statement is equivalent to the following statements: 
select region as r from sale_detail distribute by region;
select region as r from sale_detail distribute by r;

SORT BY (sort_condition)

sort_conditionはオプションです。 ほとんどの場合、SORT BYはDISTRIBUTE BYと共に使用されます。 SORT BYを使用する場合は、次のルールに従う必要があります。

  • デフォルトでは、データは昇順でソートされます。 データを降順でソートする場合は、DESCキーワードが必要です。

  • SORT BYの前にDISTRIBUTE byがある場合、SORT BYは、指定した列の値に基づいてDISTRIBUTE BYの結果をソートします。

    • 次のステートメントは、sale_detailテーブルからregion列とtotal_price列の値をクエリし、region列の値に基づいてクエリ結果に対してハッシュ分割を実行し、total_price列の値に基づいて分割結果を昇順にソートします。 例:

      -- Insert data into the sale_detail table to display the data rendering effect. 
      insert into sale_detail partition (sale_date='2014', region='shanghai') values ('null','c5',null),('s6','c6',100.4),('s7','c7',100.5);
      select region,total_price from sale_detail distribute by region sort by total_price;

      次の応答が返されます。

      +------------+-------------+
      | region     | total_price |
      +------------+-------------+
      | shanghai   | NULL        |
      | china      | 100.1       |
      | china      | 100.2       |
      | china      | 100.3       |
      | shanghai   | 100.4       |
      | shanghai   | 100.5       |
      +------------+-------------+
    • 次のステートメントは、sale_detailテーブルからregion列とtotal_price列の値を照会し、region列の値に基づいてクエリ結果に対してハッシュ分割を実行し、total_price列の値に基づいて分割結果を降順でソートします。 例:

      select region,total_price from sale_detail distribute by region sort by total_price desc;

      次の応答が返されます。

      +------------+-------------+
      | region     | total_price |
      +------------+-------------+
      | shanghai   | 100.5       |
      | shanghai   | 100.4       |
      | china      | 100.3       |
      | china      | 100.2       |
      | china      | 100.1       |
      | shanghai   | NULL        |
      +------------+-------------+
  • SORT BYの前にDISTRIBUTE BYがない場合、SORT BYは各リデューサーに配布されるデータをソートします。

    これにより、各リデューサの出力データが順番にソートされ、ストレージ圧縮率が向上します。 データの読み取り中にデータがフィルタリングされる場合、この方法はディスクから読み取られるデータの量を減らし、その後のグローバルソートの効率を向上させます。 例:

    select region,total_price from sale_detail sort by total_price desc;

    次の応答が返されます。

    +------------+-------------+
    | region     | total_price |
    +------------+-------------+
    | china      | 100.3       |
    | china      | 100.2       |
    | china      | 100.1       |
    | shanghai   | 100.5       |
    | shanghai   | 100.4       |
    | shanghai   | NULL        |
    +------------+-------------+
説明
  • ORDER BY、DISTRIBUTE BY、またはSORT BY句の列は、SELECTステートメントの出力列のエイリアスで指定する必要があります。 列エイリアスは中国語とすることができる。

  • MaxComputeでは、SELECTステートメントの後にORDER BY、DISTRIBUTE BY、またはSORT BY句が実行されます。 したがって、ORDER BY、DISTRIBUTE BY、またはSORT BYの列は、SELECTステートメントの出力列のエイリアスで指定する必要があります。

  • ORDER BYは、DISTRIBUTE BYまたはSORT BYと同時に使用することはできません。 同様に、GROUP BYDISTRIBUTE BYまたはSORT BYと同時に使用することはできません。

LIMIT <number>

LIMIT <number> はオプションです。 limit <number>numberは、表示できる行の数を制限する定数です。 numberの値は32ビットの整数で、最大値は2,147,483,647です。

説明

LIMIT <number> は、分散クエリシステムのデータをスキャンしてフィルタリングするために使用されます。 LIMIT <number> を使用すると、返されるデータ量は減少しません。 したがって、計算コストは低減されない。

次のセクションでは、LIMIT <number> の制限と、これらの制限を回避する方法について説明します。

  • ORDER BYLIMIT <number> と共に使用する必要があります。

    ORDER BYは、単一ノードのすべてのデータをソートします。 デフォルトでは、ORDER ByはLIMIT <number> と共に使用され、単一のノードが大量のデータを処理しないようにします。 次の方法を使用して、このlimitを回避できます。

    • プロジェクトの制限を回避するには、setproject odps.sql.validate.orderby.limit=false; コマンドを実行します。

    • セッションの制限を回避するには、実行するsql文を指定してset odps. SQL. validate.orderby.limit=false; コマンドをコミットして実行します。

      説明

      このlimitを回避した後、1つのノードに大量のデータを並べ替えると、より多くのリソースと時間が消費されます。

  • 限られた行が表示されます。

    SELECT文をLIMIT <number> 句なしで実行した場合、またはLIMIT <number> 句で指定した数が表示できる行の最大数 (n) を超えた場合、最大n行を表示できます。

    表示できる行の最大数は、プロジェクトによって異なります。 次のいずれかの方法を使用して、最大数を制御できます。

    • プロジェクトデータ保護が無効になっている場合は、odpscmd config.iniファイルを変更します。

      odpscmd config.iniファイルでuse_instance_tunnelをtrueに設定します。 instance_tunnel_max_recordパラメーターが設定されていない場合、表示できる行数は制限されません。 それ以外の場合、表示できる行数はinstance_tunnel_max_recordパラメーターによって制限されます。 instance_tunnel_max_recordパラメーターの最大値は10000です。 InstanceTunnelの詳細については、「使用上の注意事項」をご参照ください。

    • プロジェクトデータ保護が有効になっている場合、表示できる行数はREAD_TABLE_MAX_ROWパラメーターによって制限されます。 このパラメータの最大値は10000です。

    説明

    SHOW SecurityConfiguration; コマンドを実行して、ProjectProtectionの値を表示できます。 ProjectProtectionがtrueに設定されている場合、ビジネス要件に基づいてプロジェクトデータ保護を無効にするかどうかを判断できます。 set ProjectProtection=false; コマンドを実行して、プロジェクトデータ保護を無効にします。 デフォルトでは、ProjectProtectionはfalseに設定されています。 プロジェクトデータ保護の詳細については、「プロジェクトデータ保護」をご参照ください。

ウィンドウ句 (window_clause)

ウィンドウ句の詳細については、「構文」をご参照ください。

分割サイズのヒント

分割サイズのヒントはオプションです。 分割サイズを変更して、サブタスクの並列処理を制御し、コンピューティングパフォーマンスを調整できます。 分割サイズはテーブルに適用できます。 分割サイズの単位はMBです。 デフォルト値は256 MBです。

  • シナリオ

    • 多数のサブタスクがジョブ内のリソースを待機しているが、サブタスクにリソースを割り当てることができない場合は、分割サイズを大きくしてサブタスクの並列処理を減らすことができます。 このようにして、サブタスクの開始と停止の時間が短縮されます。

    • 数百のサブタスクなど、サブタスクの並列性が低く、現在のサブタスクが予想される期間内に結果を返さない場合は、リソースプール内の一部のリソースが使用可能かどうかを確認します。 十分なリソースが利用可能な場合は、分割サイズを小さくして、サブタスクの並列処理を増やすことができます。 これにより、ジョブの実行時間を短縮できます。

  • 注意事項

    • クラスタ化されたテーブルに分割サイズヒントを使用し、計算パフォーマンスを最適化するためにテーブルに対してバケット化操作が実行された場合、分割サイズヒントは無効です。

    • 分割サイズの値を、128 MBや512 MBなど、256 MBの倍数または倍数の値に変更できます。

    • SQL文でテーブル内のデータを複数回読み取る場合、分割には最小の分割サイズが使用されます。 たとえば、srcテーブルは2回読み取られます。

      • 一方の分割サイズが1 MBに設定され、他方の分割サイズが10 MBに設定されている場合、1 MBが分割に使用されます。

      • 一方の分割サイズが1 MBに設定され、もう一方の分割サイズが設定されていない場合、1 MBが分割に使用されます。

  • 例:

    -- Set the split size to 1 MB. This setting indicates that a job is split into subtasks based on a size of 1 MB when data in the src table is read.
    select a.key from src a /*+split_size(1)*/ join src2 b on a.key=b.key;