sql >> データベース >  >> RDS >> PostgreSQL

関数を分割-返されたレコードを複数の列に分割

    Postgresで9.3 以降、これはLATERALで解決するのが最適です。 参加:

    SELECT *
    FROM   actors a 
    JOIN   movies_actors ma on a.actor_id = ma.movie_id 
    LEFT   JOIN LATERAL hi_lo(a.actor_id, length(a.name), ma.movie_id) x ON true
    LIMIT  10;
    

    関数の繰り返し評価を回避します(出力の列ごとに、いずれかの方法で入力行ごとに関数を呼び出す必要があります)。
    LEFT JOIN LATERAL ... ON true 関数が行を返さない場合に左側から行を削除しないようにするには:

    • LATERALとPostgreSQLのサブクエリの違いは何ですか?

    コメントのフォローアップ:

    関数呼び出しによって生成された展開された列のみ

    SELECT x.*  -- that's all!
    FROM   actors a 
    JOIN   movies_actors ma on a.actor_id = ma.movie_id 
    LEFT   JOIN LATERAL hi_lo(a.actor_id, length(a.name), ma.movie_id) x ON true
    LIMIT  10;
    

    ただし、他の列は気にしないため、次のように簡略化できます。

    SELECT x.*
    FROM   actors a 
    JOIN   movies_actors ma on a.actor_id = ma.movie_id 
         , hi_lo(a.actor_id, length(a.name), ma.movie_id) x
    LIMIT  10;
    

    これは暗黙のCROSS JOIN LATERAL 。関数が実際に「行なし」を返すことがある場合、結果は異なる可能性があります。行のNULL値は取得されず、それらの行は削除されるだけです。LIMIT もう数えません。

    古いバージョンの場合 (または一般的に)正しい構文で複合型を分解することもできます:

    SELECT *, (hi_lo(a.actor_id, length(a.name), ma.movie_id)).*  -- note extra parentheses!
    FROM   actors a 
    JOIN   movies_actors ma on a.actor_id = ma.movie_id 
    LIMIT  10;

    欠点は、Postgresクエリプランナーの弱点により、関数が関数出力の列ごとに1回評価されることです。呼び出しをサブクエリまたはCTEに移動し、外側のSELECTの行タイプを分解することをお勧めします 。いいね:

    SELECT actor_id, movie_id, (x).*  -- explicit column names for the rest
    FROM  (
       SELECT *, hi_lo(a.actor_id, length(a.name), ma.movie_id) AS x
       FROM   actors a 
       JOIN   movies_actors ma on a.actor_id = ma.movie_id 
       LIMIT  10
       ) sub;
    

    ただし、個々の列に名前を付ける必要があり、SELECT *で逃げることはできません。 結果の行タイプに冗長性がある場合を除きます。関連:

    • 複合結果を展開するときに、同じ関数を複数回呼び出すことは避けてください
    • SQLクエリで(func())。*構文を使用して複数の関数の評価を回避するにはどうすればよいですか?



    1. Oracleデータベースで日付形式を変更する方法

    2. SQLServerの概要

    3. SQLServerデータベースのバージョン管理

    4. 64ビットマシンで32ビットモードでOracleClientを実行する