Ваша первоначальная идея кажется правильной.
Кстати, n² является квадратичным, а не экспоненциальным.
MySQL должен справиться с этим очень хорошо.
CREATE TABLE score (
id integer PRIMARY KEY AUTOINCREMENT NOT NULL,
player1_id integer NOT NULL,
player2_id integer NOT NULL,
score_p1 integer NOT NULL,
score_p2 integer NOT NULL,
chal_date date KEY NOT NULL,
/*UNIQUE KEY p1p2 (player1_id, player2_id),*/
FOREIGN KEY p1 (player1_id) REFERENCES player.id
ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY p2 (player2_id) REFERENCES player.id
ON DELETE CASCADE ON UPDATE CASCADE)
Engine=InnoDB;
Обратите внимание, что вы создаете только строкукогда реальный вызов имел место, и оценка должна быть записана.Таким образом, у вас будет ровно один ряд на вызов.Если одни и те же игроки могут бросать вызов друг другу более одного раза, вам следует удалить уникальный ключ p1p2.
Примеры использования
Теперь, если вы хотите узнать, сколько очков игрокуВы набрали
SELECT ifnull(sum(a.score_p1),0) + ifnull(sum(b.score_p2),0) AS total_score
FROM player
INNER JOIN score a ON (a.player1_id = player.id)
INNER JOIN score b ON (b.player2_id = player.id)
WHERE player.id = 587;
Если вы хотите знать всех игроков, с которыми вы столкнулись, вы делаете
SELECT score.player1 as opponent FROM score
WHERE score.player2 = 587
UNION ALL
SELECT score.player2 as opponent FROM score
WHERE score.player1 = 587;
Если вы делаете небольшой трюк и добавляете следующий триггер, вы можетеforce that player1.id
DELIMITER $$
CREATE TRIGGER bi_score_each BEFORE INSERT ON score FOR EACH ROW
BEGIN
DECLARE temp integer;
/*Force player1.id to always be smaller than player2.id*/
IF new.player1_id > new.player2_id THEN BEGIN
SET temp = new.player1_id;
SET new.player1_id = new.player2_id;
SET new.player2_id = temp;
END; END IF;
END$$
DELIMITER;
Теперь вы можете упростить свой запрос, чтобы увидеть совокупный счет между двумя игроками.
@p1:= 578;
@p2:= 789;
SELECT sum(score.score_p1) as score_p1
,sum(score.score_p2) as score_p2
FROM score
WHERE score.player1_id = if(@p1<@p2,@p1,@p2)
AND score.player2.id = if(@p1>@p2,@p1,@p2);
Используйте следующий запрос, чтобы выбрать всех игроковигрок боролся со счетами
SELECT score.player2_id as opponent_id
,sum(score.score_p2) as opponent_score
,sum(score.score_p1) as player_score
,p2.name as opponent_name
,p1.name as player_name
FROM score
INNER JOIN player p2 ON (p2.id = score.player2_id)
INNER JOIN player p1 ON (p1.id = score.player1_id)
WHERE player1_id = 587
GROUP BY player2.id
UNION ALL
SELECT score.player1_id as opponent_id
,sum(score.score_p1) as opponent_score
,sum(score.score_p2) as player_score
,p1.name as opponent_name
,p2.name as player_name
FROM score
INNER JOIN player p2 ON (p2.id = score.player2_id)
INNER JOIN player p1 ON (p1.id = score.player1_id)
WHERE player2_id = 587
GROUP BY player1.id
Надежды, это дает вам представление о том, что возможно.