- カテゴリ:
RESULT_SCAN¶
結果がテーブルであるかのように、以前のコマンドの結果セット(クエリを実行した24時間以内)を返します。これは、次のいずれかからの出力を処理する場合に特に便利です。
SHOW または、実行した DESC[RIBE] コマンド。
Snowflake Information Schema または Account Usage などのメタデータまたはアカウントの使用情報で実行したクエリ。
呼び出した ストアドプロシージャの結果。
24時間が経過していない限り、コマンド/クエリは現在のセッションまたは過去のセッションを含む他のセッションから取得できます。この時間は調整できません。詳細については、 保存済みのクエリ結果の使用 をご参照ください。
- こちらもご参照ください:
DESCRIBE RESULT (アカウントとセッション DDL)
構文¶
RESULT_SCAN ( { '<query_id>' | LAST_QUERY_ID() } )
引数¶
query_id
またはLAST_QUERY_ID()
実行したクエリのID(任意のセッションの過去24時間以内)または LAST_QUERY_ID 過去のクエリID 関数です。現在のセッション内のクエリの ID を返します。
使用上の注意¶
元のクエリを手動で実行した場合、元のクエリを実行したユーザーのみが RESULT_SCAN 関数を使用してクエリの出力を処理できます。ACCOUNTADMIN 権限を持つユーザであっても、 RESULT_SCAN を呼び出して他のユーザのクエリの結果にアクセスすることはできません。
元のクエリが タスク を介して実行される場合、特定のユーザーではなく、タスクを所有するロールがクエリをトリガーして実行します。ユーザまたはタスクが同じロールで操作されている場合、 RESULT_SCAN を使用してクエリ結果にアクセスできます。
Snowflakeは、すべてのクエリ結果を24時間保存します。この関数は、この期間内に実行されたクエリの結果のみを返します。
結果セットにはメタデータが関連付けられていないため、大きな結果の処理は、実際のテーブルをクエリする場合よりも遅くなる可能性があります。
RESULT_SCAN を含むクエリには、元のクエリにはなかったフィルターや ORDER BY句などの句を含めることができます。これにより、結果セットの絞り込みや変更ができます。
RESULT_SCAN では、元のクエリが行を返したのと同じ順序で行を返すことが保証されていません。特定の順序を指定するために、 RESULT_SCAN クエリに ORDER BY 句を含めることができます。
特定のクエリの ID を取得するには、次のいずれかの方法を使用します。
- Classic Console:
次のいずれかの場所で、提供されたリンクをクリックして IDを表示/コピーします。
- SQL:
次の関数のいずれかを実行します。
QUERY_HISTORY , QUERY_HISTORY_BY_* テーブル関数 。
LAST_QUERY_ID 関数(クエリが現在のセッションで実行された場合)。
例:
SELECT LAST_QUERY_ID(-2);
これは、 RESULT_SCANの入力として LAST_QUERY_ID を使用することと同等です。
RESULT_SCAN が重複する列名を含むクエリ出力(たとえば、重複する列名を持つ2つのテーブルを JOINed するクエリ)を処理する場合、 RESULT_SCAN は変更された名前を持つ重複した列を参照し、元の名前に「_1」、「_2」などを追加します。例については、以下の 例 セクションをご参照ください。
ベクトル化スキャナーを使用してクエリされたParquetファイルのタイムスタンプが、異なるタイムゾーンの時刻を表示することがありました。すべてのタイムスタンプデータを標準タイムゾーンに変換するには、 CONVERT_TIMEZONE 関数を使用します。
照合の詳細¶
RESULT_SCAN
が前のステートメントの結果を返す場合、 RESULT_SCAN
は返される値の照合順序仕様を保持します。
例¶
簡単な例¶
現在のセッションの最新のクエリの結果から 1
より大きいすべての値を取得します。
SELECT $1 AS value FROM VALUES (1), (2), (3); +-------+ | VALUE | |-------| | 1 | | 2 | | 3 | +-------+ SELECT * FROM TABLE(RESULT_SCAN(LAST_QUERY_ID())) WHERE value > 1; +-------+ | VALUE | |-------| | 2 | | 3 | +-------+
現在のセッションで2番目に新しいクエリからすべての値を取得します。
SELECT * FROM table(RESULT_SCAN(LAST_QUERY_ID(-2)));
現在のセッションの最初のクエリからすべての値を取得します。
SELECT * FROM table(RESULT_SCAN(LAST_QUERY_ID(1)));
指定されたクエリの結果の c2
列から値を取得します。
SELECT c2 FROM TABLE(RESULT_SCAN('ce6687a4-331b-4a57-a061-02b2b0f0c17c'));
DESCRIBE および SHOW コマンドを使用した例¶
DESCRIBE USER コマンドの結果を処理して、関心のある特定のフィールド、例えばユーザーの既定のロールを取得します。 DESC USER
コマンドからの出力列名は小文字で生成されたため、コマンドはクエリ内の列名を区切り識別子表記(二重引用符)で囲み、クエリの列名がスキャンしている出力の列名と一致することを確認します。
DESC USER jessicajones; SELECT "property", "value" FROM TABLE(RESULT_SCAN(LAST_QUERY_ID())) WHERE "property" = 'DEFAULT_ROLE' ;
SHOW TABLES コマンドの結果を処理して、21日より古い空のテーブルを抽出します。SHOW コマンドは小文字の列名を生成するため、コマンドは名前を引用符で囲み、大文字と小文字を区別して使用します。
SHOW TABLES; -- Show the tables that are more than 21 days old and that are empty -- (i.e. tables that I might have forgotten about). SELECT "database_name", "schema_name", "name" as "table_name", "rows", "created_on" FROM table(RESULT_SCAN(LAST_QUERY_ID())) WHERE "rows" = 0 AND "created_on" < DATEADD(day, -21, CURRENT_TIMESTAMP()) ORDER BY "created_on";
SHOW TABLES コマンドの結果を処理して、テーブルをサイズの降順に抽出します。また、この例では、 UDF を使用して、テーブルサイズを少し読みやすい形式で表示しています。
-- Show byte counts with suffixes such as "KB", "MB", and "GB". CREATE OR REPLACE FUNCTION NiceBytes(NUMBER_OF_BYTES INTEGER) RETURNS VARCHAR AS $$ CASE WHEN NUMBER_OF_BYTES < 1024 THEN NUMBER_OF_BYTES::VARCHAR WHEN NUMBER_OF_BYTES >= 1024 AND NUMBER_OF_BYTES < 1048576 THEN (NUMBER_OF_BYTES / 1024)::VARCHAR || 'KB' WHEN NUMBER_OF_BYTES >= 1048576 AND NUMBER_OF_BYTES < (POW(2, 30)) THEN (NUMBER_OF_BYTES / 1048576)::VARCHAR || 'MB' ELSE (NUMBER_OF_BYTES / POW(2, 30))::VARCHAR || 'GB' END $$ ; SHOW TABLES; -- Show all of my tables in descending order of size. SELECT "database_name", "schema_name", "name" as "table_name", NiceBytes("bytes") AS "size" FROM table(RESULT_SCAN(LAST_QUERY_ID())) ORDER BY "bytes" DESC;
ストアドプロシージャの使用例¶
ストアドプロシージャコールは値を返します。ただし、ストアドプロシージャコールを別のステートメントに埋め込むことはできないため、この値を直接処理することはできません。この制限を回避するには、 RESULT_SCAN
を使用して、ストアドプロシージャによって返される値を処理します。簡単な例を以下に示します。
最初に、
CALL
から返された後に処理できる「複雑な」値(この場合は JSON互換データを含む文字列)を返すプロシージャを作成します。CREATE OR REPLACE PROCEDURE return_JSON() RETURNS VARCHAR LANGUAGE JavaScript AS $$ return '{"keyA": "ValueA", "keyB": "ValueB"}'; $$ ;次に、プロシージャを呼び出します。
CALL return_JSON(); +--------------------------------------+ | RETURN_JSON | |--------------------------------------| | {"keyA": "ValueA", "keyB": "ValueB"} | +--------------------------------------+次の3つの手順では、結果セットからデータを抽出します。
最初の(そして唯一の)列を取得します。
SELECT $1 AS output_col FROM table(RESULT_SCAN(LAST_QUERY_ID())); +--------------------------------------+ | OUTPUT_COL | |--------------------------------------| | {"keyA": "ValueA", "keyB": "ValueB"} | +--------------------------------------+出力を VARCHAR から VARIANTに変換します。
SELECT PARSE_JSON(output_col) AS JSON_COL FROM table(RESULT_SCAN(LAST_QUERY_ID())); +---------------------+ | JSON_COL | |---------------------| | { | | "keyA": "ValueA", | | "keyB": "ValueB" | | } | +---------------------+キー「keyB」に対応する値を抽出します。
SELECT JSON_COL:keyB FROM table(RESULT_SCAN(LAST_QUERY_ID())); +---------------+ | JSON_COL:KEYB | |---------------| | "ValueB" | +---------------+
前の例で抽出されたのと同じデータを抽出する、よりコンパクトな方法を次に示します。この例では、ステートメントは少なくなっていますが、読みづらくなっています。
CALL return_JSON(); +--------------------------------------+ | RETURN_JSON | |--------------------------------------| | {"keyA": "ValueA", "keyB": "ValueB"} | +--------------------------------------+ SELECT JSON_COL:keyB FROM ( SELECT PARSE_JSON($1::VARIANT) AS JSON_COL FROM table(RESULT_SCAN(LAST_QUERY_ID())) ); +---------------+ | JSON_COL:KEYB | |---------------| | "ValueB" | +---------------+
CALL からの出力は、関数名を列名として使用します。例:
+--------------------------------------+ | RETURN_JSON | +--------------------------------------+ | {"keyA": "ValueA", "keyB": "ValueB"} | +--------------------------------------+
クエリでその列名を使用できます。次に、追加のコンパクトバージョンを示します。このバージョンでは、列は列番号ではなく名前で参照されます。
CALL return_JSON(); +--------------------------------------+ | RETURN_JSON | |--------------------------------------| | {"keyA": "ValueA", "keyB": "ValueB"} | +--------------------------------------+ SELECT JSON_COL:keyB FROM ( SELECT PARSE_JSON(RETURN_JSON::VARIANT) AS JSON_COL FROM table(RESULT_SCAN(LAST_QUERY_ID())) ); +---------------+ | JSON_COL:KEYB | |---------------| | "ValueB" | +---------------+
列名が重複している例¶
次の例は、元のクエリに重複する列名がある場合、 RESULT_SCAN が代替列名を効果的に参照することを示しています。
同じ名前の列が少なくとも1つある2つのテーブルを作成します。
CREATE TABLE employees (id INT);CREATE TABLE dependents (id INT, employee_id INT);2つのテーブルにデータをロードします。
INSERT INTO employees (id) VALUES (11);INSERT INTO dependents (id, employee_id) VALUES (101, 11);次に、出力に同じ名前の2つの列が含まれるクエリを実行します。
SELECT * FROM employees INNER JOIN dependents ON dependents.employee_ID = employees.id ORDER BY employees.id, dependents.id ; +----+-----+-------------+ | ID | ID | EMPLOYEE_ID | |----+-----+-------------| | 11 | 101 | 11 | +----+-----+-------------+Snowsight での出力は、 Snowsight が重複する列名を自動的に処理するため、上に示した出力とは異なることに注意してください。
次に、 RESULT_SCAN を呼び出して、そのクエリの結果を処理します。結果に同じ名前を持つ異なる列がある場合、 RESULT_SCAN は、最初の列には元の名前を使用し、2番目の列には変更された一意の名前を割り当てます。名前を一意にするために、 RESULT_SCAN は、「_<n>」というサフィックスを名前に付加します。「<n>」は、前の列の名前とは異なる名前を生成する、次に使用可能な数字です。
SELECT id, id_1, employee_id FROM TABLE(RESULT_SCAN(LAST_QUERY_ID())) WHERE id_1 = 101; +----+------+-------------+ | ID | ID_1 | EMPLOYEE_ID | |----+------+-------------| | 11 | 101 | 11 | +----+------+-------------+