在 table 中查找并创建缺失的行
Finding and creating missing rows in table
您好 postgres 专家,
我有一个应用程序,用户可以在其中投票。我的架构如下所示:
polls
table:
id
name
1
Favorite fruit
options
table:
id
poll_id
content
1
1
apple
2
1
orange
3
1
grape
4
1
banana
participants
table:
id
poll_id
name
1
1
John
2
1
Jane
votes
table:
id
poll_id
participant_id
option_id
type
1
1
1
1
yes
2
1
1
3
yes
3
1
2
2
yes
我决定不为 votes
table 中的“反对”票创建行,我认为这会“节省 space”,这是一个糟糕的选择。我现在意识到这不是一个好主意,因为将来我想知道用户是否明确投了“否”票,或者是否可能在他们投票后添加了该选项,因此没有选择它的选项。因此,我需要 运行 一个查询,该查询将填充现有 participants
votes
table 中所有缺失的“否”票。最终结果应如下所示:
votes
table:
id
poll_id
participant_id
option_id
type
1
1
1
1
yes
2
1
1
3
yes
3
1
2
2
yes
4
1
1
2
no
5
1
1
4
no
6
1
2
1
no
7
1
2
3
no
8
1
2
4
no
我有一个 dbfiddle,其中包含所有数据:
https://dbfiddle.uk/?rdbms=postgres_14&fiddle=7d0f4c83095638cc6006b1d7876d0e01
附带问题: 我是否应该关注此架构中投票的大小 table?我预计它会迅速膨胀到数百万行。 options
作为数组存储在 polls
table 中,而 votes
存储在 participants
table 中的模式是更好的主意吗?
感谢您的帮助。
您似乎正在寻找 JOIN
of participants
with options
, EXCEPT
已经在 votes
中的行。有多种方法可以做到这一点,但最直接的方法是:
INSERT INTO votes(poll_id, participant_id, option_id, type)
SELECT poll_id, participant_id, option_id, 'no'
FROM (
SELECT o.poll_id, p.id, o.id
FROM options o
JOIN participants p ON o.poll_id = p.poll_id
EXCEPT
SELECT poll_id, participant_id, option_id
FROM votes
) AS missing;
或者:
INSERT INTO votes(poll_id, participant_id, option_id, type)
SELECT o.poll_id, p.id, o.id, 'no'
FROM options o
JOIN participants p ON o.poll_id = p.poll_id
WHERE NOT EXISTS (
SELECT *
FROM votes
WHERE poll_id = o.poll_id AND participant_id = p.id AND option_id = o.id
);
或者,假设您已经在 votes
上有 UNIQUE
索引,只需
INSERT INTO votes(poll_id, participant_id, option_id, type)
SELECT o.poll_id, p.id, o.id, 'no'
FROM options o
ON CONFLICT ON CONSTRAINT votes_p_key
DO NOTHING;
您好 postgres 专家,
我有一个应用程序,用户可以在其中投票。我的架构如下所示:
polls
table:
id | name |
---|---|
1 | Favorite fruit |
options
table:
id | poll_id | content |
---|---|---|
1 | 1 | apple |
2 | 1 | orange |
3 | 1 | grape |
4 | 1 | banana |
participants
table:
id | poll_id | name |
---|---|---|
1 | 1 | John |
2 | 1 | Jane |
votes
table:
id | poll_id | participant_id | option_id | type |
---|---|---|---|---|
1 | 1 | 1 | 1 | yes |
2 | 1 | 1 | 3 | yes |
3 | 1 | 2 | 2 | yes |
我决定不为 votes
table 中的“反对”票创建行,我认为这会“节省 space”,这是一个糟糕的选择。我现在意识到这不是一个好主意,因为将来我想知道用户是否明确投了“否”票,或者是否可能在他们投票后添加了该选项,因此没有选择它的选项。因此,我需要 运行 一个查询,该查询将填充现有 participants
votes
table 中所有缺失的“否”票。最终结果应如下所示:
votes
table:
id | poll_id | participant_id | option_id | type |
---|---|---|---|---|
1 | 1 | 1 | 1 | yes |
2 | 1 | 1 | 3 | yes |
3 | 1 | 2 | 2 | yes |
4 | 1 | 1 | 2 | no |
5 | 1 | 1 | 4 | no |
6 | 1 | 2 | 1 | no |
7 | 1 | 2 | 3 | no |
8 | 1 | 2 | 4 | no |
我有一个 dbfiddle,其中包含所有数据:
https://dbfiddle.uk/?rdbms=postgres_14&fiddle=7d0f4c83095638cc6006b1d7876d0e01
附带问题: 我是否应该关注此架构中投票的大小 table?我预计它会迅速膨胀到数百万行。 options
作为数组存储在 polls
table 中,而 votes
存储在 participants
table 中的模式是更好的主意吗?
感谢您的帮助。
您似乎正在寻找 JOIN
of participants
with options
, EXCEPT
已经在 votes
中的行。有多种方法可以做到这一点,但最直接的方法是:
INSERT INTO votes(poll_id, participant_id, option_id, type)
SELECT poll_id, participant_id, option_id, 'no'
FROM (
SELECT o.poll_id, p.id, o.id
FROM options o
JOIN participants p ON o.poll_id = p.poll_id
EXCEPT
SELECT poll_id, participant_id, option_id
FROM votes
) AS missing;
或者:
INSERT INTO votes(poll_id, participant_id, option_id, type)
SELECT o.poll_id, p.id, o.id, 'no'
FROM options o
JOIN participants p ON o.poll_id = p.poll_id
WHERE NOT EXISTS (
SELECT *
FROM votes
WHERE poll_id = o.poll_id AND participant_id = p.id AND option_id = o.id
);
或者,假设您已经在 votes
上有 UNIQUE
索引,只需
INSERT INTO votes(poll_id, participant_id, option_id, type)
SELECT o.poll_id, p.id, o.id, 'no'
FROM options o
ON CONFLICT ON CONSTRAINT votes_p_key
DO NOTHING;