情况:
比赛有10名球员,每队5名。总共有100名玩家,每场比赛可以在十个位置中的任何一个中拥有任何玩家。我需要提取以下给出的两名球员:
我目前的方法(太慢,可能不起作用):
我制作了三张桌子,“玩家”,“匹配”和“匹配_玩家”,将比赛映射到玩家中。比赛中的“wins_team”列表示哪支球队获胜(0 =球队A,1 =球队B),match_players表中的列“位置”表示球员在阵容中的位置。 0-4在A队,5-9在B队。
玩家
player_id
43179582
63260623
31250276
54829050
22257854
etc...
匹配
match_id winning_team
95824317 0
06236326 0
02763125 1
90505482 0
78544325 1
etc...
matches_players
relation_id match_id player_id position
1 95824317 43179582 1
2 95824317 63260623 5
3 06236326 43179582 7
4 06236326 54829050 0
5 06236326 22257854 4
etc...
这是我用于在同一个团队中找到匹配和赢取英雄数量的声明(经过12个小时的冲浪并尝试理解SQL):
SELECT
COUNT(*) AS match_count,
SUM(CASE WHEN team = winning_team THEN 1 ELSE 0 END) AS win_count
FROM
(SELECT
matches.match_id,
(CASE WHEN position < 5 THEN 0 ELSE 1 END) AS team,
winning_team
FROM matches INNER JOIN matches_players ON matches.match_id = matches_players.match_id
WHERE player_id = [____] OR player_id = [____]
GROUP BY match_id, team HAVING COUNT(*) = 2)
AS pair_matches
它似乎有效,但速度非常慢(250,000场比赛中90秒以上),理想情况下我希望在同一个查询中有相反的团队成绩(这应该比两个单独的查询更快,不是吗?)可以查询变得更快/更好?是否存在数据库设计缺陷?
我非常感谢任何有帮助的人。欢迎任何地区的建议。感谢。
答案 0 :(得分:1)
我认为应该这样做或至少给你一个提示
-- How many matches were player A and player B allies?
select DISTINCT (match_id) from MATCHES_PLAYERS where PLAYER_ID='43179582' or PLAYER_ID='63260623' group by MATCH_ID;
-- How many of these did they win?
select PLAYER_ID, count(WINNING_TEAM)
from
(select PLAYER_ID, WINNING_TEAM, POsition from MATCHES_PLAYERS mp, matches m where mp.MATCH_ID=m.MATCH_ID and position<=4 and WINNING_TEAM=0
union all
select PLAYER_ID, WINNING_TEAM, POsition from MATCHES_PLAYERS mp, matches m where mp.MATCH_ID=m.MATCH_ID and position>4 and WINNING_TEAM=1)
group by PLAYER_id;
-- How many matches were player A and player B opponents?
select mp1.*, m.WINNING_TEAM, mp2.PLAYER_ID as opponent from MATCHES_PLAYERS mp1, MATCHES_PLAYERS mp2, matches m where mp1.MATCH_ID=m.MATCH_ID and mp1.MATCH_ID=mp2.MATCH_ID and mp1.PLAYER_ID!=mp2.PLAYER_ID and (mp1.PLAYER_id in (43179582, 63260623) and mp2.player_id in (43179582, 63260623))
select DISTINCT mp1.MATCH_ID from MATCHES_PLAYERS mp1, MATCHES_PLAYERS mp2, matches m where mp1.MATCH_ID=m.MATCH_ID and mp1.MATCH_ID=mp2.MATCH_ID and mp1.PLAYER_ID!=mp2.PLAYER_ID and (mp1.PLAYER_id in (43179582, 63260623) and mp2.player_id in (43179582, 63260623))
-- How many of these did player A win?
select
mp1.*, m.WINNING_TEAM, mp2.PLAYER_ID as opponent
from MATCHES_PLAYERS mp1, MATCHES_PLAYERS mp2, matches m
where mp1.MATCH_ID=m.MATCH_ID
and mp1.MATCH_ID=mp2.MATCH_ID
and mp1.PLAYER_ID!=mp2.PLAYER_ID
and
(
mp1.PLAYER_id=43179582
and mp2.player_id=63260623
)
and mp1.position<=4
and m.WINNING_TEAM=0
答案 1 :(得分:0)
我认为接受的答案中有错误(在“玩家 A 和 B 的盟友有多少场比赛?”部分)
我的回答使用子查询和 ROUND(position/4) 从位置 0..3 转换为团队 0,从位置 4..7 转换为团队 1。
首先,此脚本创建表(Oracle SQL 风格)。索引仅在主键上自动创建:
CREATE TABLE players(player_id NUMBER PRIMARY KEY);
CREATE TABLE matches(match_id NUMBER PRIMARY KEY, winning_team NUMBER(1) CHECK(winning_team IN (0, 1)));
CREATE TABLE matches_players(relation_id NUMBER PRIMARY KEY, match_id NUMBER NOT NULL REFERENCES matches(match_id), player_id NUMBER NOT NULL REFERENCES players(player_id), position NUMBER NOT NULL CHECK(position < 8));
让我们加载一些数据:
INSERT INTO players
SELECT 43179582 FROM DUAL
UNION ALL SELECT 63260623 FROM DUAL
UNION ALL SELECT 31250276 FROM DUAL
UNION ALL SELECT 54829050 FROM DUAL
UNION ALL SELECT 22257854 FROM DUAL
;
-- match_id winning_team
INSERT INTO matches
SELECT 95824317, 0 FROM DUAL
UNION ALL SELECT 06236326, 0 FROM DUAL
UNION ALL SELECT 02763125, 1 FROM DUAL
UNION ALL SELECT 90505482, 0 FROM DUAL
UNION ALL SELECT 78544325, 1 FROM DUAL
;
-- relation_id match_id player_id position
DELETE matches_players;
INSERT INTO matches_players
SELECT 1, 95824317, 43179582, 1 FROM DUAL
UNION ALL SELECT 2, 95824317, 63260623, 5 FROM DUAL
UNION ALL SELECT 3, 06236326, 43179582, 7 FROM DUAL
UNION ALL SELECT 4, 06236326, 54829050, 0 FROM DUAL
UNION ALL SELECT 5, 06236326, 22257854, 4 FROM DUAL
UNION ALL SELECT 6, 06236326, 63260623, 4 FROM DUAL
;
然后,这些是查询:
-- How many matches were player A and player B allies?
SELECT COUNT(*) FROM matches_players mp WHERE player_id = 63260623
AND (match_id, ROUND(position/4)) IN (
SELECT match_id, ROUND(position/4) FROM matches_players WHERE player_id = 22257854
);
-- How many of these did they win?
SELECT COUNT(*) FROM matches_players mp WHERE player_id = 63260623
AND (match_id, ROUND(position/4)) IN (
SELECT match_id, ROUND(position/4) FROM matches_players WHERE player_id = 22257854
)
AND EXISTS(SELECT NULL FROM matches m WHERE m.match_id = mp.match_id AND m.winning_team = ROUND(mp.position/4))
;
-- How many matches were player A and player B opponents?
SELECT COUNT(*) FROM matches_players mp WHERE player_id = 63260623
AND (match_id, ROUND(position/4)) IN (
SELECT match_id, -(ROUND(position/4) - 1) FROM matches_players WHERE player_id = 54829050
);
-- How many of these did player A win?
SELECT COUNT(*) FROM matches_players mp WHERE player_id = 54829050
AND (match_id, ROUND(position/4)) IN (
SELECT match_id, -(ROUND(position/4) - 1) FROM matches_players WHERE player_id = 63260623
)
AND EXISTS(SELECT NULL FROM matches m WHERE m.match_id = mp.match_id AND m.winning_team = ROUND(mp.position/4))
;
如果你想加快这些查询的速度,你可以在 position 和 Winning_team 上创建索引:
CREATE INDEX matches_idx ON matches(winning_team);
CREATE INDEX matches_players_idx ON matches_players(ROUND(position/4));
如果你想要超高速并且你的数据库引擎支持位图索引,你可以尝试:
CREATE BITMAP INDEX matches_idx ON matches(winning_team);
CREATE BITMAP INDEX matches_players_idx ON matches_players(ROUND(position/4));