I am recording sports match data in the form of 3 tables:
- matches (id, start_time)
- match_teams (id, match_id, team_id, score)
- match_players (id, match_id, team_id, player_id)
Each match consists of several teams, each team consists of several players (effectively a list of lists). With team_id and player_id as foreign keys on the teams and players table respectively.
Using the above structure, I need to insert into the matches table first and use the returned id to pass into match_teams and match_players.
Following this question I am using the following CTE to accomplish this where I am inserting one match:
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);
I want to insert multiple matches at once in one query. I am using offset and limit to select the right match id for the players/ teams.
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
This works, but it seems like a bit of a hacky solution. Is there a best practice way to do this?
Update I've realised I have some redundant columns. I've fixed this up, but I don't think it changes the question significantly. My question is more like "is using offset and limit like this best practice?"