MaxComputeでは、SELECTステートメントを使用してデータをクエリできます。 このトピックでは、MaxComputeのSELECTステートメントの構文について説明します。 このトピックでは、SELECTステートメントを使用して、ネストされたクエリ、並べ替え、グループごとのクエリなどの操作を実行する方法についても説明します。
SELECTステートメントを実行する前に、ターゲットテーブルでSelect権限が付与されていることを確認してください。 詳細は、「MaxCompute権限」をご参照ください。
次のプラットフォームでステートメントを実行できます。
概要
SELECT文は、指定された条件を満たすデータをテーブルから照会するために使用されます。 次の表に、さまざまなシナリオで実行できるクエリ操作を示します。
クエリ操作 | 説明 |
クエリの結果に基づいてさらにクエリを実行できます。 | |
2つのデータセットの共通部分、和集合、または補足セットを取得できます。 | |
| |
右のテーブルを使用して左のテーブルのデータをフィルタリングし、左のテーブルにのみ表示されるデータを取得できます。 | |
1つの大きなテーブルと1つ以上の小さなテーブルに対して | |
結合する2つのテーブルにホットキー値が含まれている場合、ロングテールの問題が発生する可能性があります。 2つのテーブルからホットキー値を抽出し、ホットキー値の結合結果と非ホットキー値の結合結果を別々に計算してから、計算されたデータを結合することができます。 | |
LATERAL VIEWとユーザー定義のテーブル値関数 (UDTF) を使用して、1行のデータを複数の行に分割できます。 | |
複数のディメンションからのデータを集計および分析できます。 | |
| |
分割サイズを変更して、サブタスクの並列処理を制御できます。 | |
MaxComputeでは、デルタテーブルに対してタイムトラベルクエリと増分クエリを実行できます。
|
制限事項
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;次の応答が返されます。
FAILED: ODPS-0130161:[1,6] Parse exception - recursive cte A is invalid, it must have an initial_part and a recursive_part, which must be connected by UNION ALLAがBを参照し、BがAを参照する場合、参照は無効である。 循環参照には対応していません。 CTEの不正な使用:
WITH A AS (SELECT * FROM B ), B AS (SELECT * FROM A ) SELECT * FROM B;次の応答が返されます。
FAILED: ODPS-0130071:[1,26] Semantic analysis exception - while resolving view B - [1,51]recursive function call is not supported, cycle is A->B->A
正しい使用法のサンプルステートメント:
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句とともにアスタリスク (*) を使用して、フィルター条件を指定することもできます。次のステートメントは、
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を使用してフィルター条件を指定します。 例:
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, ...) から...;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はcol1_name、exp2はcol2_name、...) から...;ステートメントを使用して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句は、フィルター条件を指定します。 where_conditionがパーティションテーブルに使用される場合、列の剪定を実行できます。 where_conditionを使用する場合は、次のルールに従う必要があります。
リレーショナル演算子でwhere_conditionを使用して、指定された条件を満たすデータを取得します。 関係演算子は次のとおりです。
>、<、=、>=、<=、<>LIKEとRLIKEIN、NOT INBETWEEN…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';
Column式 (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句は集計関数で使用され、データをフィルタリングします。 例:
-- 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 (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を回避できます。プロジェクトの
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)
ウィンドウ句の詳細については、「構文」をご参照ください。