text
sの配列をUUID
sの配列にキャストするにはどうすればよいですか?
2つのテーブルjoin
とusers
の間でprojects
を実行する必要があります。
users
テーブルには、プロジェクトIDをテキストとして含むproject_ids
という名前の配列フィールドがあります。
projects
テーブルには、id
という名前のUUIDフィールドがありました。
私の最初のアイデアは次のようなクエリでした。
SELECT * FROM projects
JOIN users ON
projects.id = ANY(users.project_ids)
しかし、users.project_ids
はUUID
sではないため、これは機能しません。
projects.id = ANY(users.project_ids::uuid[])
そして:
projects.id = ANY(ARRAY[users.project_ids]::uuid[])
しかしどちらも機能しません:
ERROR: invalid input syntax for type uuid: ""
更新
@a_horse_with_no_nameは間違いなく正しいです。最良のオプションは、UUIDの配列を使用することです。
ここでの質問は、text
の配列をuuid
の配列に変更するにはどうすればよいですか?
users
テーブルは現在空です(0レコード)。
私が試してみました
ALTER TABLE "users" ALTER COLUMN "project_ids" SET DATA TYPE UUID USING "project_ids"::uuid[];
生成する
エラー:列 "product_ids"のUSING句の結果は、タイプuuidに自動的にキャストできませんヒント:明示的なキャストを追加する必要がある場合があります。
ALTER TABLE "users" ALTER COLUMN "product_ids" SET DATA TYPE UUID USING "product_ids" :: UUID;
私も試しました
ALTER TABLE "users" ALTER COLUMN "project_ids" SET DATA TYPE UUID[] USING "project_ids"::uuid[];
生成する
エラー:列「project_ids」のデフォルトは、タイプuuid []に自動的にキャストできません
列はデフォルトで空の配列に設定されます。
PGバージョン10.4を実行していますが、project_ids
は現在text[] nullable
です。
コメントされたように、列_project_ids
_は_uuid[]
_である必要があり、これは問題を排除します。また、より効率的です。
変更するには(アサートしたような列に不正なデータがない場合):
_ALTER TABLE users ALTER COLUMN project_ids DROP DEFAULT;
ALTER TABLE users
ALTER COLUMN project_ids SET DATA TYPE uuid[] USING project_ids::uuid[];
_
誤って_uuid[]
_ではなくuuid
がありました。
この:
_ERROR: default for column "product_ids" cannot be cast automatically to type uuid[]
_
..は、列にデフォルト値が設定されていることを意味します。その式は自動的に変換できません。タイプを変更する前に削除してください。新しいDEFAULT
は後で追加できます。
元の状況で効率的な修正は、空の文字列を配列から削除することです array_remove()
beforeキャスト(Postgres 9.3以降が必要):
_SELECT *
FROM users u
JOIN projects p ON p.id = ANY(array_remove(u.project_ids, '')::uuid[]);
_
...afterその_text[]
_列に空の文字列が含まれる理由を調査します。
関連:
クエリの_[INNER] JOIN
_は、_projects_ids
_に有効なプロジェクトがないユーザーを結果から削除します。通常は、これらもkeepしたいです。代わりに_LEFT [OUTER] JOIN
_を使用します(users
を最初に)。
JOIN
は、重複したエントリをいずれかの方法で折りたたみます。重複するエントリを表す場合は、代わりに結合の前にネストを解除します。
また、単にIDの配列をプロジェクト名の配列に解決することを目的としている場合は、配列要素の元の順序を維持することもできます。
_SELECT *
FROM users u
LEFT JOIN LATERAL (
SELECT ARRAY(
SELECT project_name -- use the actual column(s) of your case
FROM unnest (array_remove(u.project_ids, '')::uuid[]) WITH ORDINALITY AS p(id, ord)
JOIN projects USING (id)
ORDER BY ord
)
) p(projects) ON true;
_
db <> fiddle here(大まかに基づいて McNetsのフィドル )
関連:
create table users (user_id int, projects text[]); insert into users values (1, (array['a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11', 'b0eebc99-9c0b-4ef8-bb6d-cbb9bd380a11'])::text[]); insert into users values (2, (array['a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11', 'b0eebc99-9c0b-4ef8-bb6d-cbb9bd380a11', 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'])::text[]); insert into users values (3, (array['f0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11', '', 'e0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'])::text[]);
create table projects (project_id uuid); insert into projects values ('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid), ('d0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid), ('e0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid);
a_horse_with_no_name が指摘したように、配列要素に値がない場合は失敗します。変換できません。
select user_id, project_id from projects join users on project_id = any(projects::uuid[])
エラー:タイプuuidの無効な入力構文: ""
ただし、project_id
このようにテキストとして:
select user_id, project_id from projects join users on project_id::text = any(projects);
user_id | project_id ------:| :----------------------------------- 1 | a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 2 | a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 3 | e0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11
db <> fiddle ここ
または、配列を展開し(ネストを解除)、空/ null値を回避できます。
with usr as ( select user_id, unnest(projects) as project_id from users ) select user_id, projects.project_id from projects join usr on coalesce(usr.project_id, '') <> '' and usr.project_id::uuid = projects.project_id;
user_id | project_id ------:| :----------------------------------- 2 | a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 1 | a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11 3 | e0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11
db <> fiddle ここ