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

PostgreSQLでCASEを使用して、一度に複数の列に影響を与える

    1。標準SQL:LEFT JOIN 値の単一行

    LEFT JOIN 条件を使用した値の行(これにより、条件を1回評価します)。次に、を使用して、列ごとにフォールバック値を追加できます。 COALESCE()

    この構文バリアントは、複数の値を使用すると短く、わずかに高速になります。特に、高価で長い条件の場合は興味深いものです。

    SELECT COALESCE(x.txt1, trim(r2.team_name))     AS testing_testing
         , COALESCE(x.txt2, trim(r2.normal_data))   AS test_response
         , COALESCE(x.txt3, trim(r2.normal_data_2)) AS another_example
    FROM   rtp
    JOIN   rtd2 r2 ON <unknown condition> -- missing context in question
    LEFT   JOIN (
       SELECT 'testing'::text         AS txt1
            , 'test example'::text    AS txt2
            , 'test example #2'::text AS txt3
       ) x ON rtp.team_id = rtp.sub_team_id;
    

    派生テーブルx以降 シングルで構成されます 行、それ以上の条件なしで参加することは問題ありません。

    明示的な型キャスト サブクエリで必要です。 textを使用しています 例では(とにかく文字列リテラルのデフォルトです)。実際のデータ型を使用してください。構文ショートカットvalue::type Postgres固有であるため、cast(value AS type)を使用します 標準SQLの場合。

    条件がTRUEでない場合 、xのすべての値 NULLであり、COALESCE キックインします。

    または 、すべての候補値はテーブルrtd2から取得されるため 特定のケースでは、LEFT JOIN rtd2へ 元のCASEを使用する 条件とCROSS JOIN デフォルト値の行へ:

    SELECT COALESCE(trim(r2.team_name),     x.txt1) AS testing_testing
         , COALESCE(trim(r2.normal_data),   x.txt2) AS test_response
         , COALESCE(trim(r2.normal_data_2), x.txt3) AS another_example
    FROM   rtp
    LEFT   JOIN rtd2 r2 ON <unknown condition>  -- missing context in question
                       AND rtp.team_id = rtp.sub_team_id
    CROSS  JOIN (
       SELECT 'testing'::text         AS txt1
            , 'test example'::text    AS txt2
            , 'test example #2'::text AS txt3
       ) x;
    

    結合条件と残りのクエリによって異なります。

    2。 PostgreSQL固有

    2a。配列を展開する

    さまざまな列が同じデータ型を共有している場合 、サブクエリで配列を使用し、外側のSELECTで配列を展開できます :

    SELECT x.combo[1], x.combo[2], x.combo[3]
    FROM  (
       SELECT CASE WHEN rtp.team_id = rtp.sub_team_id
                THEN '{test1,test2,test3}'::text[]
                ELSE ARRAY[trim(r2.team_name)
                         , trim(r2.normal_data)
                         , trim(r2.normal_data_2)]
              END AS combo
       FROM   rtp
       JOIN   rtd2 r2 ON <unknown condition>
       ) x;
    

    列が同じデータ型を共有していない場合は、さらに複雑になります。それらすべてをtextにキャストすることができます (オプションで、外側のSELECTに変換し直します )、またはできます...

    2b。行タイプを分解します

    カスタム複合型(行型)を使用してさまざまな型の値を保持し、それを外側のSELECTで単純に*展開できます。 。 textの3つの列があるとします。 、integer およびdate繰り返しの場合 使用して、カスタム複合タイプを作成します:

    CREATE TYPE my_type (t1 text, t2 int, t3 date);
    

    または 既存のテーブルのタイプが一致する場合は、テーブル名を複合タイプとして使用できます。

    または タイプが一時的に必要な場合のみ 、TEMPORARY TABLEを作成できます 、セッションの期間中の一時タイプを登録します :

    CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date);
    

    単一のトランザクションに対してこれを行うこともできます :

    CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date) ON COMMIT DROP;
    

    次に、次のクエリを使用できます:

    SELECT (x.combo).*  -- parenthesis required
    FROM  (
       SELECT CASE WHEN rtp.team_id = rtp.sub_team_id
                 THEN ('test', 3, now()::date)::my_type  -- example values
                 ELSE (r2.team_name
                     , r2.int_col
                     , r2.date_col)::my_type
              END AS combo
       FROM   rtp
       JOIN   rtd2 r2 ON <unknown condition>
       ) x;
    

    または単に(上記と同じ、より単純、より短く、おそらく理解しにくい):

    SELECT (CASE WHEN rtp.team_id = rtp.sub_team_id
               THEN ('test', 3, now()::date)::my_type
               ELSE (r2.team_name, r2.int_col, r2.date_col)::my_type
            END).*
    FROM   rtp
    JOIN   rtd2 r2 ON <unknown condition>;
    

    CASE この方法では、式は列ごとに1回評価されます。評価が簡単でない場合は、サブクエリを使用した他のバリアントの方が高速になります。



    1. Oracleデータベースに送信されるすべてのクエリを表示する

    2. MySQLでNULL値のないレコードを選択する方法

    3. PHPでのMySQL*.sqlファイルの実行

    4. Oracleからmysqlへのデータベースミラーリング