我有两个表,用户和组:
users(user_id BIGSERIAL, email TEXT UNIQUE NOT NULL, state TEXT NOT NULL)
groups(group_id BIGSERIAL, name TEXT, members []BIGINT)
从上面可以看出,users表包含一个用户记录,其中每个记录由电子邮件地址和自动生成的user_id字段唯一标识。 groups
表包含一个members
数组,其中包含一组引用users表中user_id的BIGINT。
现在我需要一个查询,当给出两个传入参数时,email
和group_id
:
users
表是否已包含具有该电子邮件地址的记录INSERT
新记录SELECT
行的user_id
(新创建或已存在)user_id
,并将其附加到members
与传入参数匹配的组表的group_id
字段中。成员字段有可能已包含user_id
,在这种情况下,不需要执行任何操作(IOW,members
字段中的groups
字段应该没有重复值}} table。。对于1,2和3,我写了以下查询:
WITH new_row AS (
INSERT INTO users (email, state)
SELECT 'abc@abc.abcd', 'Referred'
WHERE NOT EXISTS (SELECT * FROM users WHERE email = 'abc@abc.abcd')
RETURNING *
)
SELECT user_id FROM new_row
UNION
SELECT user_id FROM users WHERE email='abc@abc.abcd';
对于4,我写了以下查询:
UPDATE groups SET members = (
SELECT ARRAY(
SELECT DISTINCT unnest(members || array[RANDOM_USER_ID]::bigint[]) ) )
WHERE group_id = INCOMING_GROUP_ID
RETURNING group_id, members;
其中第二个查询中的RANDOM_USER_ID
应替换为第一个查询中获得的user_id
。
现在将这两个查询原子地组合为单个查询的方法是什么,其中第一个查询的user_id
通过管道传输到第二个查询?我不想创建事务并独立运行两个单独的查询,并将user_id字段保存在临时位置(在我的服务器程序中)。我希望所有这些都可以在一个查询中完成。有可能吗?
如果重要的话,我将在RDS / Google CloudSQL上使用Postgresql 9.6.4(或更高版本)。
答案 0 :(得分:1)
从我看到的情况来看,我认为假设每个查询只有一个DECLARE @a VARCHAR(3);
SET @a =
(
SELECT TOP 1 sifval
FROM
(
SELECT sifval
FROM VALUTI
WHERE OZNVAL = 'EUR'
UNION
SELECT sifval
FROM KURSNA
WHERE OZNVAL = 'EUR'
) q
);
是公平的,所以你可以使用另一个CTE(为了清晰起见)和子查询:
user_id
替代方案是使用UPSERT:
WITH usr AS (
WITH new_row AS (
INSERT INTO users (email, state)
SELECT 'abc@abc.abcd', 'Referred'
WHERE NOT EXISTS (SELECT * FROM users WHERE email = 'abc@abc.abcd')
RETURNING *
)
SELECT user_id FROM new_row
UNION
SELECT user_id FROM users WHERE email='abc@abc.abcd'
)
UPDATE groups SET members = (
SELECT ARRAY(
SELECT DISTINCT unnest(members || array[(SELECT user_id FROM usr)]::bigint[]) ) )
WHERE group_id = INCOMING_GROUP_ID
RETURNING group_id, members;