次の表は、ユーザーごとに複数の電子メールアドレスを示しています。
これをユーザークエリの列にフラット化する必要があります。作成日に基づいて「最新」の3つのメールアドレスを教えてください。
user.name | user.id | email1 | email2 | email3**
Mary | 123 | [email protected] | [email protected] | [email protected]
Joe | 345 | [email protected] | [NULL] | [NULL]
tablefunc モジュールのcrosstab()
を使用します。
_SELECT * FROM crosstab(
$$SELECT user_id, user_name, rn, email_address
FROM (
SELECT u.user_id, u.user_name, e.email_address
, row_number() OVER (PARTITION BY u.user_id
ORDER BY e.creation_date DESC NULLS LAST) AS rn
FROM usr u
LEFT JOIN email_tbl e USING (user_id)
) sub
WHERE rn < 4
ORDER BY user_id
$$
, 'VALUES (1),(2),(3)'
) AS t (user_id int, user_name text, email1 text, email2 text, email3 text);
_
最初のパラメーターには特別な意味のないドル引用符を使用しました。一般的なケースであるクエリ文字列内の単一引用符をエスケープする必要がある場合に便利です。
詳細な説明と手順はこちら:
特に、「余分な列」の場合:
特別な困難は次のとおりです。
キー名の欠如。
->サブクエリで row_number()
に置き換えます。
さまざまな数のメール。
->最大値に制限します。外側の3つのSELECT
そしてcrosstab()
を2つのパラメーターとともに使用して、可能なキーのリストを提供します。
_NULLS LAST
_の _ORDER BY
_に注意してください 。
この質問を見つけて、これに動的な解決策を必要とする誰かが正確に3つではなく未定義の列数を転置する必要がある場合、ここでニースの解決策を見つけることができます: https://github.com/ jumpstarter-io/colpivot
上記のコードは本当に助けになりました。今、ピボットテーブルにフィールドを追加しようとしています。
SELECT * INTO temp_pivot_table FROM crosstab(
$$SELECT lead_id, magazine_id, days_between_mailers, rn
FROM (
SELECT u.lead_id, u.magazine_id, u.days_between_mailers
, row_number() OVER (PARTITION BY u.lead_id
ORDER BY u.id ASC NULLS LAST) AS rn
FROM temp_mailer_stats u
) sub
WHERE rn <= 3
ORDER BY lead_id
$$
, 'VALUES (1),(2),(3),(4),(5),(6)'
) AS t (lead_id int, magazine1 text, magazine2 text, magazine3 text,
days_between1 integer, days_between2 integer, days_between3 integer);
もちろん、別々のテーブルを作成してからそれらを結合することもできますが、理想的なステップを保存できる場合。
助けてくれてありがとう。