我正在以3张桌子的形式记录体育比赛数据:
每场比赛由几支球队组成,每支球队由几名球员组成(实际上是一份名单)。将team_id和player_id分别作为球队和球员桌上的外键。
使用上面的结构,我需要先插入 matches 表,然后使用返回的id传递给match_teams和match_players。
关注this question我正在使用以下CTE完成此操作,我将插入一个匹配项:
WITH a AS (INSERT INTO matches (start_time)
VALUES ('"0001-01-01T00:00:00+00:00"')
RETURNING id),
b AS (INSERT INTO match_teams (match_id, team_id, score)
VALUES
((SELECT id FROM a), 5, 1),
((SELECT id FROM a), 6, 2))
INSERT INTO match_players (match_id, team_id, player_id)
VALUES
((SELECT id FROM a), 5, 3),
((SELECT id FROM a), 5, 4),
((SELECT id FROM a), 6, 5)
((SELECT id FROM a), 6, 6);
我想在一个查询中一次插入多个匹配项。我使用偏移和限制来为球员/球队选择正确的比赛ID。
WITH a AS (INSERT INTO matches (start_time)
VALUES
('"0001-01-01T00:00:00+00:00"'), -- 1st match
('"0001-01-01T00:00:00+00:00"') -- 2nd match
RETURNING id),
b AS (INSERT INTO match_teams (match_id, team_id, score)
VALUES
((SELECT id FROM a OFFSET 0 LIMIT 1), 5, 1), -- 1st match
((SELECT id FROM a OFFSET 0 LIMIT 1), 6, 2), -- 1st match
((SELECT id FROM a OFFSET 1 LIMIT 1), 5, 2), -- 2nd match
((SELECT id FROM a OFFSET 1 LIMIT 1), 6, 1)) -- 2nd match
INSERT INTO match_players (match_id, team_id, player_id)
VALUES
((SELECT id FROM a OFFSET 0 LIMIT 1), 5, 3), -- 1st match
((SELECT id FROM a OFFSET 0 LIMIT 1), 6, 4), -- 1st match
((SELECT id FROM a OFFSET 1 LIMIT 1), 5, 5), -- 2nd match
((SELECT id FROM a OFFSET 1 LIMIT 1), 6, 6); -- 2nd match
这很有效,但它看起来像是一个hacky解决方案。有最佳实践方法吗?
更新我意识到我有一些冗余列。我已经解决了这个问题,但我不认为这会显着改变这个问题。我的问题更像是“正在使用偏移和限制这种最佳实践吗?”
答案 0 :(得分:3)
使用偏移和限制就像这种最佳做法一样吗?
当然不是。这非常低效且使用起来非常不方便,特别是对于大量的比赛。
您可以使用row_number()
选择正确的id
加入teams
,players
加入teams
:
with teams (rn, team_ids, scores) as (
values
(1, array[5, 6], array[1, 2]), -- match #1 in this query
(2, array[5, 6], array[2, 1]) -- match #2 in this query
),
players (rn, team_ids, player_ids) as (
values
(1, array[5, 5, 6, 6], array[3, 4, 5, 6]),
(2, array[5, 5, 6, 6], array[3, 4, 5, 6])
),
ins_matches as (
insert into matches (start_time)
values
('"0001-01-01t00:00:00+00:00"'),
('"0001-01-01t00:00:00+00:00"')
returning id
),
matches as (
select id, row_number() over (order by id) rn
from ins_matches -- rn - number of match in this query
),
ins_teams as (
insert into match_teams (match_id, team_id, score)
select id, unnest(team_ids), unnest(scores)
from matches
join teams using(rn)
)
insert into match_players (match_id, team_id, player_id)
select id, unnest(team_ids), unnest(player_ids)
from matches
join players using(rn);
答案 1 :(得分:0)
就我而言,我有route_sources
和routes
route_sources
将route_source_id
作为PK routes
将route_source_id
作为FK
-- GOT ID TO ROUTE_SOURCES FROM SEQUENCE
int_route_source_id = nextval('traffic.route_sources_route_source_id_seq'::regclass);
-- CREATE NEW RECORD FOR ROUTE_SOURCES
INSERT INTO traffic.Route_Sources
(route_source_id, sql, ini_avl_id, ini_link_id)
VALUES
(int_route_source_id, strSQL, A.avl_id, A.link_id, ini_offset);
-- CREATE THE ROUTE
INSERT INTO traffic.Routes
(route_source_id, seq_id, node_id, link_id, cost)
SELECT int_route_source_id, seq, id1 AS node, id2 AS edge, cost::numeric(11,4)
FROM pgr_trsp;