次のようなJSONの列を含むテーブルがあるとします。
{"payload":[{"type":"b","value":"9"}, {"type":"a","value":"8"}]}
{"payload":[{"type":"c","value":"7"}, {"type":"b","value":"3"}]}
Prestoクエリを記述して、すべてのエントリの平均b
値を取得するにはどうすればよいですか?
これまでのところ、私はHiveの 側面図が爆発する のようなものを使用する必要があると思います。これはPrestoの cross join unnest に相当します。
しかし、私はcross join unnest
のPrestoクエリを作成する方法に固執しています。
cross join unnest
を使用してすべての配列要素を展開し、それらを選択するにはどうすればよいですか?
これがその例です
_with example(message) as (
VALUES
(json '{"payload":[{"type":"b","value":"9"},{"type":"a","value":"8"}]}'),
(json '{"payload":[{"type":"c","value":"7"}, {"type":"b","value":"3"}]}')
)
SELECT
n.type,
avg(n.value)
FROM example
CROSS JOIN
UNNEST(
CAST(
JSON_EXTRACT(message,'$.payload')
as ARRAY(ROW(type VARCHAR, value INTEGER))
)
) as x(n)
WHERE n.type = 'b'
GROUP BY n.type
_
with
は、example
という名前の共通テーブル式(CTE)を定義し、列のエイリアスはmessage
です。
VALUES
は逐語的なテーブル行セットを返します
UNNEST
は、単一行の列内の配列を取得し、配列の要素を複数の行として返します。
CAST
は、JSON
タイプをARRAY
に必要なUNNEST
タイプに変更しています。簡単に_ARRAY<MAP<
_であった可能性がありますが、列名を指定し、select句でドット表記を使用できるため、_ARRAY(ROW(
_の方が優れていると思います。
_JSON_EXTRACT
_はjsonPath式を使用して、payload
キーの配列値を返します
avg()
および_group by
_は使い慣れたSQLである必要があります。
ご指摘のとおり、これはついにPresto0.79で実装されました。 :)
here からのキャストの構文の例を次に示します。
select cast(cast ('[1,2,3]' as json) as array<bigint>);
特別なアドバイスですが、PrestoにはHiveのような「文字列」タイプはありません。つまり、配列に文字列が含まれている場合は、必ずタイプ 'varchar'を使用してください。そうしないと、 'タイプ配列が存在しません'というエラーメッセージが表示され、誤解を招く可能性があります。
select cast(cast ('["1","2","3"]' as json) as array<varchar>);
問題は、古いバージョンのPrestoを実行していたことでした。
unnest
はバージョン0.79で追加されました