MaxComputeでは、SELECT
ステートメントを使用してデータをクエリできます。 このトピックでは、MaxComputeのSELECT
ステートメントの構文について説明します。 このトピックでは、SELECTステートメントを使用して、ネストされたクエリ、並べ替え、グループごとのクエリなどの操作を実行する方法についても説明します。
SELECT
ステートメントを実行する前に、ターゲットテーブルでSelect権限が付与されていることを確認してください。 詳細は、「MaxCompute権限」をご参照ください。
次のプラットフォームでステートメントを実行できます。
概要
SELECT
文は、指定された条件を満たすデータをテーブルから照会するために使用されます。 次の表に、さまざまなシナリオで実行できるクエリ操作を示します。
クエリ操作 | 説明 |
クエリの結果に基づいてさらにクエリを実行できます。 | |
2つのデータセットの共通部分、和集合、または補足セットを取得できます。 | |
| |
右のテーブルを使用して左のテーブルのデータをフィルタリングし、左のテーブルにのみ表示されるデータを取得できます。 | |
1つの大きなテーブルと1つ以上の小さなテーブルに対して | |
結合する2つのテーブルにホットキー値が含まれている場合、ロングテールの問題が発生する可能性があります。 2つのテーブルからホットキー値を抽出し、ホットキー値の結合結果と非ホットキー値の結合結果を別々に計算してから、計算されたデータを結合することができます。 | |
LATERAL VIEWとユーザー定義のテーブル値関数 (UDTF) を使用して、1行のデータを複数の行に分割できます。 | |
複数のディメンションからのデータを集計および分析できます。 | |
| |
分割サイズを変更して、サブタスクの並列処理を制御できます。 | |
MaxComputeでは、トランザクションテーブル2.0のテーブルに対して、タイムトラベルクエリと増分クエリを実行できます。
|
制限事項
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 | +-----------+------------+
次のステートメントでは、DISTINCTはGROUP 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_expr
はexcept(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を使用して、指定された条件を満たすデータを取得します。 関係演算子は次のとおりです。
>
、<
、=
、>=
、<=
、<>
LIKE
とRLIKE
イン
、イン
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がdeterministic
UDFと見なされます。 上記の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 BY
はSELECT
よりも優先されます。 したがって、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 BY
はDISTRIBUTE BY
またはSORT BY
と同時に使用することはできません。
LIMIT <number>
LIMIT <number> はオプションです。 limit <number>
のnumber
は、表示できる行の数を制限する定数です。 numberの値は32ビットの整数で、最大値は2,147,483,647です。
LIMIT <number>
は、分散クエリシステムのデータをスキャンしてフィルタリングするために使用されます。 LIMIT <number>
を使用すると、返されるデータ量は減少しません。 したがって、計算コストは低減されない。
次のセクションでは、LIMIT <number> の制限と、これらの制限を回避する方法について説明します。
ORDER BY
はLIMIT <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;