Одним из способов сделать это эффективно является дальнейшая нормализация таблицы путем нормализации столбца позиции.
Нормализованная таблица
CREATE TABLE IF NOT EXISTS lineup (
match_id INTEGER NOT NULL REFERENCES matches,
position_id INTEGER NOT NULL REFERENCES positions,
player_id INTEGER NOT NULL REFERENCES players
CONSTRAINT lineups_pk PRIMARY KEY (match_id, position_id, player_id)
);
Таблица позиций
Вы такженужна таблица позиций, что-то вроде:
CREATE TABLE IF NOT EXISTS positions (
position_id INTEGER,
position TEXT, -- or whatever your character type of choice is
CONSTRAINT positions_pk PRIMARY KEY (position_id)
);
Этот подход имеет то преимущество, что обеспечивает соблюдение ограничения, которое вы хотите применить, и дополнительное преимущество в том, что он будет гибким в будущем, если вы определите себянеобходимо добавить дополнительную информацию о позициях, игроках или матчах.
Просмотр данных
Затем вы можете представить данные в нужном формате, выполнив что-то вроде этого:
SELECT
match_id
, a.player_id AS pos_1
, b.player_id AS pos_2
, c.player_id AS pos_3
, d.player_id AS pos_4
, e.player_id AS pos_5
, f.player_id AS pos_6
FROM (SELECT match_id, player_id FROM lineup WHERE position_id = 1) a
LEFT JOIN (SELECT match_id, player_id FROM lineup WHERE position_id = 2) b USING (match_id)
LEFT JOIN (SELECT match_id, player_id FROM lineup WHERE position_id = 3) c USING (match_id)
LEFT JOIN (SELECT match_id, player_id FROM lineup WHERE position_id = 4) d USING (match_id)
LEFT JOIN (SELECT match_id, player_id FROM lineup WHERE position_id = 5) e USING (match_id)
LEFT JOIN (SELECT match_id, player_id FROM lineup WHERE position_id = 6) f USING (match_id);
Это немного сложнее, чтобы настроить его таким образом, но как только у вас есть запрос, вы можете создать его как представление, а затем вы всегда получите его, и вы получите выгоду отдополнительная нормализация.Этот способ также облегчает ответы на такие вопросы, как "во сколько матчей играл player_id 1?"и «они всегда играют в одной и той же позиции?»
Обеспечение заполнения всех шести позиций
Первоначально в этом ответе не было требования о том, что все шесть позиций должны быть заполнены,Без дополнений это гарантирует, что каждая позиция перечислимая заполнена, но допускает возможность того, что позиция не будет вставлена.Есть два способа решения этой проблемы:
Убедитесь, что на вставке с помощью метода нанесения / вставки
- Плюсы: быстрее, легче
- Минусы: не применяется на уровне базы данных, возможно отсутствие данных
При вставке / удалении с помощью триггера базы данных
- Плюсы: обеспечивает на уровне базы данных, делает невозможным (если реализовано правильно) отсутствие пропусков
- Минусы: здесь будут триггеры
DBA StackExchange имеет отличный вопрос и ответ о том, как реализовать такого рода ограничения с использованием триггеров.