我不是MySQL专家,因为它可能会从我的查询中显示出来,但我已经设法让我的查询给我想要的结果,但对我来说似乎很慢:
SELECT
bouts.bout_id,
bouts.bout_date,
bouts.winner,
bouts.result,
bouts.ended_in_round,
bouts.total_rounds,
bouts.verified AS verified,
CONCAT(opponent.first_name, ' ', opponent.last_name) AS opponent_name,
opponent.last_name AS opponent_lastname,
opponent.id AS opponent_id,
IF(opponent.id = bouts.boxer_1, bouts.boxer_1_weight, bouts.boxer_2_weight) AS opp_weight,
IF(opponent.id = bouts.boxer_1, bouts.boxer_2_weight, bouts.boxer_1_weight) AS fighter_weight,
SUM(opp_bouts.ended_in_round) AS opp_total_rounds_boxed,
SUM(IF(opp_bouts.winner = -1,1,0)) AS opp_draws,
SUM(IF(opp_bouts.winner = opponent.id,1,0)) AS opp_wins,
COUNT(opp_bouts.bout_id) AS opp_fights,
IF(opponent.id = bouts.boxer_1, bouts.bxr2_power_points, bouts.bxr1_power_points) AS boxer_power,
IF(opponent.id = bouts.boxer_1, bouts.bxr2_chin_points, bouts.bxr1_chin_points) AS boxer_chin,
IF(opponent.id = bouts.boxer_1, bouts.bxr2_boxer_points, bouts.bxr1_boxer_points) AS boxer_boxer,
SUM(IF(opponent.id = opp_bouts.boxer_1, opp_bouts.bxr1_power_points, opp_bouts.bxr2_power_points)) AS opp_power,
SUM(IF(opponent.id = opp_bouts.boxer_1, opp_bouts.bxr1_chin_points, opp_bouts.bxr2_chin_points)) AS opp_chin,
SUM(IF(opponent.id = opp_bouts.boxer_1, opp_bouts.bxr1_boxer_points, opp_bouts.bxr2_boxer_points)) AS opp_boxer,
SUM(IF(opponent.id = opp_bouts.boxer_1, opp_bouts.bxr1_exp_points, opp_bouts.bxr2_exp_points)) AS opp_experience,
MAX(IF(opp_bouts.verified = 1, opp_bouts.bout_date, 0)) AS verified_up_to,
MAX(opp_bouts.bout_date) AS opp_last_bout
FROM
bouts
LEFT JOIN boxers opponent ON opponent.id=IF(bouts.boxer_2 = '" . $boxer_id . "', bouts.boxer_1, bouts.boxer_2)
LEFT JOIN bouts opp_bouts ON (opp_bouts.boxer_1=opponent.id OR opp_bouts.boxer_2=opponent.id) AND opp_bouts.bout_date < bouts.bout_date
WHERE bouts.bout_date < '" . $to_date . "' AND (bouts.boxer_1 = '" . $boxer_id . "' OR bouts.boxer_2 = '" . $boxer_id . "')
GROUP BY bouts.bout_id
ORDER BY bouts.bout_date DESC
bouts
大约有11,570行,boxers
大约有86,370行,目前运行时间介于0.6500 - 0.7500之间。我在boxers.id
和bouts.bout_id
上有一个主键,在bouts.boxer_1
和bouts.boxer_2
上有索引,但我对使用索引的了解也不是很好。
查询这么慢是否正常,有什么办法可以帮助加快速度吗?
更新
解释查询结果。如果这不正确,你必须告诉我......
更新2
布特表格结构:
拳击手桌结构:
更新3
好的,可能会取得一些进展......
如果我改变
LEFT JOIN bouts opp_bouts ON (opp_bouts.boxer_1=opponent.id OR opp_bouts.boxer_2=opponent.id) AND opp_bouts.bout_date < bouts.bout_date
到:
LEFT JOIN bouts opp_bouts ON (opp_bouts.boxer_1=opponent.id) AND opp_bouts.bout_date < bouts.bout_date
它将查询速度提高到0.0250左右,这似乎是一个很大的速度问题。我可以改进OR功能还是以不同的方式进行?
更新4
感谢Kickstart我现在拥有以下代码,速度要快得多,但我不是100%我已经完成了所有事情......或者我是否应该在某些列上设置索引以进一步加快速度?我不确定它会如何扩大但是枯萎,但它可能是我能得到的最好的?
bouts
现在有~46,066行和boxers
~90,531,查询运行在0.0466,索引在bout_date上,并且都是boxer_1 / 2.
SELECT bout_id,
bout_date,
winner,
result,
ended_in_round,
total_rounds,
verified,
opponent_first_name,
opponent_last_name,
opponent_id,
opp_weight,
fighter_weight,
SUM(opp_ended_in_round) AS opp_total_rounds_boxed,
SUM(IF(opp_winner = -1,1,0)) AS opp_draws,
SUM(IF(opp_winner = opponent_id,1,0)) AS opp_wins,
COUNT(opp_id) AS opp_fights,
boxer_power,
boxer_chin,
boxer_boxer,
SUM(opp_power_rating) AS opp_power,
SUM(opp_chin_rating) AS opp_chin,
SUM(opp_boxer_rating) AS opp_boxer,
SUM(opp_exp_rating) AS opp_experience,
MIN(IF(opp_verified = 1,9999-01-01 , opp_bout_date)) AS verified_up_to,
MAX(opp_bout_date) AS opp_last_bout
FROM (
SELECT bouts.bout_id, bouts.total_rounds, bouts.result, bouts.verified, opp_bouts.verified AS opp_verified, opp_bouts.bout_id AS opp_id, bouts.winner, opp_bouts.winner AS opp_winner, bouts.ended_in_round, opp_bouts.ended_in_round AS opp_ended_in_round, bouts.boxer_2_weight AS opp_weight, bouts.bxr1_power_points AS boxer_power, opp_bouts.bxr1_power_points AS opp_power_rating , opp_bouts.bxr1_chin_points AS opp_chin_rating, opp_bouts.bxr1_boxer_points AS opp_boxer_rating, opp_bouts.bxr1_exp_points AS opp_exp_rating, bouts.bxr1_chin_points AS boxer_chin, bouts.bxr1_boxer_points AS boxer_boxer, bouts.boxer_1_weight AS fighter_weight, bouts.boxer_2 AS opponent_id, bouts.bout_date, opp_bouts.bout_date AS opp_bout_date, opponent.first_name AS opponent_first_name, opponent.last_name AS opponent_last_name
FROM bouts
LEFT JOIN boxers opponent ON opponent.id = boxer_2
LEFT JOIN bouts opp_bouts ON opp_bouts.boxer_1 = opponent.id AND opp_bouts.bout_date < bouts.bout_date
WHERE bouts.bout_date < 'NOW()'
AND bouts.boxer_1 = '63514'
UNION ALL
SELECT bouts.bout_id, bouts.total_rounds, bouts.result, bouts.verified, opp_bouts.verified AS opp_verified, opp_bouts.bout_id AS opp_id, bouts.winner, opp_bouts.winner AS opp_winner, bouts.ended_in_round, opp_bouts.ended_in_round AS opp_ended_in_round, bouts.boxer_2_weight AS opp_weight, bouts.bxr1_power_points AS boxer_power, opp_bouts.bxr2_power_points AS opp_power_rating, opp_bouts.bxr2_chin_points AS opp_chin_rating, opp_bouts.bxr2_boxer_points AS opp_boxer_rating, opp_bouts.bxr2_exp_points AS opp_exp_rating, bouts.bxr1_chin_points AS boxer_chin, bouts.bxr1_boxer_points AS boxer_boxer, bouts.boxer_1_weight AS fighter_weight, bouts.boxer_2 AS opponent_id, bouts.bout_date, opp_bouts.bout_date AS opp_bout_date, opponent.first_name AS opponent_first_name, opponent.last_name AS opponent_last_name
FROM bouts
LEFT JOIN boxers opponent ON opponent.id = boxer_2
LEFT JOIN bouts opp_bouts ON opp_bouts.boxer_2 = opponent.id AND opp_bouts.bout_date < bouts.bout_date
WHERE bouts.bout_date < 'NOW()'
AND bouts.boxer_1 = '63514'
UNION ALL
SELECT bouts.bout_id, bouts.total_rounds, bouts.result, bouts.verified, opp_bouts.verified AS opp_verified, opp_bouts.bout_id AS opp_id, bouts.winner, opp_bouts.winner AS opp_winner, bouts.ended_in_round, opp_bouts.ended_in_round AS opp_ended_in_round, bouts.boxer_1_weight AS opp_weight, bouts.bxr2_power_points AS boxer_power, opp_bouts.bxr1_power_points AS opp_power_rating, opp_bouts.bxr1_chin_points AS opp_chin_rating, opp_bouts.bxr1_boxer_points AS opp_boxer_rating, opp_bouts.bxr1_exp_points AS opp_exp_rating, bouts.bxr2_chin_points AS boxer_chin, bouts.bxr2_boxer_points AS boxer_boxer, bouts.boxer_2_weight AS fighter_weight, bouts.boxer_1 AS opponent_id, bouts.bout_date, opp_bouts.bout_date AS opp_bout_date, opponent.first_name AS opponent_first_name, opponent.last_name AS opponent_last_name
FROM bouts
LEFT JOIN boxers opponent ON opponent.id = boxer_1
LEFT JOIN bouts opp_bouts ON opp_bouts.boxer_1 = opponent.id AND opp_bouts.bout_date < bouts.bout_date
WHERE bouts.bout_date < 'NOW()'
AND bouts.boxer_2 = '63514'
UNION ALL
SELECT bouts.bout_id, bouts.total_rounds, bouts.result, bouts.verified, opp_bouts.verified AS opp_verified, opp_bouts.bout_id AS opp_id, bouts.winner, opp_bouts.winner AS opp_winner, bouts.ended_in_round, opp_bouts.ended_in_round AS opp_ended_in_round, bouts.boxer_1_weight AS opp_weight, bouts.bxr2_power_points AS boxer_power, opp_bouts.bxr2_power_points AS opp_power_rating, opp_bouts.bxr2_chin_points AS opp_chin_rating, opp_bouts.bxr2_boxer_points AS opp_boxer_rating, opp_bouts.bxr2_exp_points AS opp_exp_rating, bouts.bxr2_chin_points AS boxer_chin, bouts.bxr2_boxer_points AS boxer_boxer, bouts.boxer_2_weight AS fighter_weight, bouts.boxer_1 AS opponent_id, bouts.bout_date, opp_bouts.bout_date AS opp_bout_date, opponent.first_name AS opponent_first_name, opponent.last_name AS opponent_last_name
FROM bouts
LEFT JOIN boxers opponent ON opponent.id = boxer_1
LEFT JOIN bouts opp_bouts ON opp_bouts.boxer_2 = opponent.id AND opp_bouts.bout_date < bouts.bout_date
WHERE bouts.bout_date < 'NOW()'
AND bouts.boxer_2 = '63514'
) AS my_table GROUP BY bout_id ORDER BY bout_date DESC
答案 0 :(得分:6)
使用IF来决定几乎所有列,无论你是指第一个还是第二个拳击手都可能会减慢速度。
可能最好有2个子选择(每个boxer_1和boxer_2一个),将结果合并在一起,然后合并到SUMs和COUNTs上。
EDIT。简要示例(不完整,因为我不完全了解所有数据的来源)。将4个查询联合在一起(对于每个boxer_1和boxer_2各自进行一次回合,并且每次对于第二次加入的回合中的一个进行回合)。使用此联合查询的结果进行实际计算。
SELECT SomeFields,
SUM(SomeField),
etc
FROM
(
SELECT bouts.boxer_1 AS boxer, bouts.boxer_2 AS opponent, opp_bouts.boxer_2 AS opponentsPrevOpponent
FROM bouts
LEFT JOIN boxers opponent ON opponent.id = bouts.boxer_2
LEFT JOIN bouts opp_bouts ON opp_bouts.boxer_1 = opponent.id AND opp_bouts.bout_date < bouts.bout_date
WHERE bouts.bout_date < '" . $to_date . "'
AND bouts.boxer_1 = '" . $boxer_id . "'
UNION ALL
SELECT bouts.boxer_1 AS boxer, bouts.boxer_2 AS opponent, opp_bouts.boxer_1 AS opponentsPrevOpponent
FROM bouts
LEFT JOIN boxers opponent ON opponent.id = bouts.boxer_2
LEFT JOIN bouts opp_bouts ON opp_bouts.boxer_2 = opponent.id AND opp_bouts.bout_date < bouts.bout_date
WHERE bouts.bout_date < '" . $to_date . "'
AND bouts.boxer_1 = '" . $boxer_id . "'
UNION ALL
SELECT bouts.boxer_2 AS boxer, bouts.boxer_1 AS opponent, opp_bouts.boxer_2 AS opponentsPrevOpponent
FROM bouts
LEFT JOIN boxers opponent ON opponent.id = bouts.boxer_1
LEFT JOIN bouts opp_bouts ON opp_bouts.boxer_1 = opponent.id AND opp_bouts.bout_date < bouts.bout_date
WHERE bouts.bout_date < '" . $to_date . "'
AND bouts.boxer_2 = '" . $boxer_id . "'
UNION ALL
SELECT bouts.boxer_2 AS boxer, bouts.boxer_1 AS opponent, opp_bouts.boxer_1 AS opponentsPrevOpponent
FROM bouts
LEFT JOIN boxers opponent ON opponent.id = bouts.boxer_1
LEFT JOIN bouts opp_bouts ON opp_bouts.boxer_2 = opponent.id AND opp_bouts.bout_date < bouts.bout_date
WHERE bouts.bout_date < '" . $to_date . "'
AND bouts.boxer_2 = '" . $boxer_id . "'
) Sub1
通过这种方式,您可以在子选择中获取所需的值,而不是在各种聚合函数上使用IF语句
答案 1 :(得分:0)
为了增加SQL查询的速度,您可以使用临时表进行左连接,然后使用所有选择的总和,如果
创建临时表new_temp_table 如 选择 * 来自您的查询
之后:
选择(所有选择代码) 来自new_temp_table
当您使用临时表时,这可能对您的情况有所帮助,不是一次查询,而是在2次或更多时间内这可以改善时间执行。 2-3查询更简单是更快解决1问题3时间复杂。连接SQL关闭后,临时表将丢弃
示例(法语):table temporaire SQL