MaxCompute は、SELECT 文の句を、記述された構文とは異なる順序で実行します。この実行順序を理解することは、特に GROUP BY、HAVING、および DISTRIBUTE BY や SORT BY といった MaxCompute 固有の句を使用する場合に、正しいクエリロジックを記述するのに役立ちます。
実行シーケンス
SELECT 構文は、SELECT、FROM、WHERE、GROUP BY、HAVING、WINDOW、QUALIFY、ORDER BY、DISTRIBUTE BY、SORT BY、LIMIT の句をサポートしています。
MaxCompute は、使用する句に応じて、これら 2 つのシーケンスのいずれかで実行します。
ORDER BYとGROUP BYは、DISTRIBUTE BYまたはSORT BYと一緒に使用することはできません。
シーケンス 1 — クエリに GROUP BY、ORDER BY、または LIMIT が含まれる場合に使用されます。
-
FROM -
WHERE -
GROUP BY -
HAVING -
SELECT -
ORDER BY -
LIMIT
シーケンス 2 — クエリに DISTRIBUTE BY または SORT BY が含まれる場合に使用されます。
-
FROM -
WHERE -
SELECT -
DISTRIBUTE BY -
SORT BY
SELECT は記述構文では最初に現れますが、FROM、WHERE、GROUP BY、HAVING が処理された後にのみ実行されます。
実行順序での文の記述
クエリロジックを読みやすくするために、MaxCompute では SELECT を先頭にするのではなく、FROM を先頭にして実行順序で SELECT 文を記述できます。この 2 つの形式は同等です。
-- 標準形式 (SELECT が先)
SELECT region, max(total_price)
FROM sale_detail
WHERE total_price > 100
GROUP BY region
HAVING sum(total_price) > 300.5
ORDER BY region
LIMIT 5;
-- 実行順序形式 (FROM が先) — 上記の文と同等
FROM sale_detail
WHERE total_price > 100
GROUP BY region
HAVING sum(total_price) > 300.5
SELECT region, max(total_price)
ORDER BY region
LIMIT 5;
完全な実行順序の構文は次のとおりです。
FROM <table_reference>
[WHERE <where_condition>]
[GROUP BY <col_list>]
[HAVING <having_condition>]
[WINDOW <window_name> AS (<window_definition>)]
[QUALIFY <expression>]
SELECT [ALL | DISTINCT] <select_expr>, <select_expr>, ...
[ORDER BY <order_condition>]
[DISTRIBUTE BY <distribute_condition> [SORT BY <sort_condition>]]
[LIMIT <number>]
サンプルデータ
このトピックの例では、sale_detail という名前のパーティションテーブルを使用します。次の文を実行して、テーブルを作成し、データを入力します。
-- 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);
-- パーティションを追加
ALTER TABLE sale_detail ADD
PARTITION (sale_date='2013', region='china')
PARTITION (sale_date='2014', region='shanghai');
-- データを挿入
INSERT INTO sale_detail PARTITION (sale_date='2013', region='china')
VALUES ('s1','c1',100.1),('s2','c2',100.2),('s3','c3',100.3);
INSERT INTO sale_detail PARTITION (sale_date='2014', region='shanghai')
VALUES ('null','c5',null),('s6','c6',100.4),('s7','c7',100.5);
テーブル全体を表示するには:
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 |
| null | c5 | NULL | 2014 | shanghai |
| s6 | c6 | 100.4 | 2014 | shanghai |
| s7 | c7 | 100.5 | 2014 | shanghai |
+------------+-------------+-------------+------------+------------+
例
例 1:シーケンス 1 (GROUP BY と ORDER BY)
パーティションを指定せずにパーティションテーブルをクエリするには、全表スキャンが必要です。有効にするには、文の前に SET odps.sql.allow.fullscan=true; を追加してください。
次の 2 つの文は同等です。どちらもシーケンス 1 を使用します。
-- 標準形式
SET odps.sql.allow.fullscan=true;
SELECT region, max(total_price)
FROM sale_detail
WHERE total_price > 100
GROUP BY region
HAVING sum(total_price) > 300.5
ORDER BY region
LIMIT 5;
-- 実行順序形式
SET odps.sql.allow.fullscan=true;
FROM sale_detail
WHERE total_price > 100
GROUP BY region
HAVING sum(total_price) > 300.5
SELECT region, max(total_price)
ORDER BY region
LIMIT 5;
結果:
+------------+------------+
| region | _c1 |
+------------+------------+
| china | 100.3 |
+------------+------------+
句の実行方法:
-
FROM
sale_detail— テーブルから行を読み取ります。 -
WHERE
total_price > 100—total_priceが 100 を超える行のみを保持します。 -
GROUP BY
region— 残りの行をリージョンでグループ化します。 -
HAVING
sum(total_price) > 300.5— 合計価格が 300.5 を超えるグループのみを保持します。 -
SELECT
region, max(total_price)— 各グループからリージョンと最大価格を射影します。 -
ORDER BY
region— 結果をリージョンでソートします。 -
LIMIT
5— 最初の 5 行を返します。
例 2:シーケンス 2 (DISTRIBUTE BY と SORT BY)
次の 2 つの文は同等です。どちらもシーケンス 2 を使用します。
-- 標準形式
SET odps.sql.allow.fullscan=true;
SELECT shop_name,
total_price,
region
FROM sale_detail
WHERE total_price > 100.2
DISTRIBUTE BY region
SORT BY total_price;
-- 実行順序形式
SET odps.sql.allow.fullscan=true;
FROM sale_detail
WHERE total_price > 100.2
SELECT shop_name,
total_price,
region
DISTRIBUTE BY region
SORT BY total_price;
結果:
+------------+-------------+------------+
| shop_name | total_price | region |
+------------+-------------+------------+
| s3 | 100.3 | china |
| s6 | 100.4 | shanghai |
| s7 | 100.5 | shanghai |
+------------+-------------+------------+
句の実行方法:
-
FROM
sale_detail— テーブルから行を読み取ります。 -
WHERE
total_price > 100.2—total_priceが 100.2 を超える行のみを保持します。 -
SELECT
shop_name, total_price, region— 3 つの列を射影します。 -
DISTRIBUTE BY
region— region 列のハッシュパーティショニングを使用して、リデューサー間で行を分散させます。 -
SORT BY
total_price— 各リデューサー内でtotal_priceによって行を昇順にソートします。