I have a pretty big SQL query to get data from multiple database tables. I use the ON
condition to check if the guild_ids are always the same and in some cases, he check’s for an user_id too.
That is my query:
SELECT
SUM( f.guild_id = 787672220503244800 AND f.winner_id LIKE '%841827102331240468%' ) AS guild_winner,
SUM( f.winner_id LIKE '%841827102331240468%' ) AS win_sum,
m.message_count,
r.bypass_role_id,
i.real_count,
i.total_count,
i.bonus_count,
i.left_count
FROM
guild_finished_giveaways AS f
JOIN guild_message_count AS m
JOIN guild_role_settings AS r
JOIN guild_invite_count AS i ON m.guild_id = f.guild_id
AND m.user_id = 841827102331240468
AND r.guild_id = f.guild_id
AND i.guild_id = f.guild_id
AND i.user_id = m.user_id
But it runs pretty slow, with over 15s. I can’t see why it needs so long.
I figured out that if I remove the "guild_invite_count" JOIN, it’s pretty fast again. Do I have some simple error here that I don’t see? Or what could be the issue?
2
Answers
Each
JOIN
expression needs it’s ownON
. Don’t wait until the end for this. As it was, the server was forced to build up a cartesian product of all those tables before narrowing them down again, and I’m surprised the query ran at all (I’d expect a syntax error for missingON
clauses).It’s also more than a little odd to use
SUM()
or any other aggregate function in the same query as non-aggregated values without aGROUP BY
clause.Are you using
InnoDB
?Does every table have a
PRIMARY KEY
?These may help:
It looks like some tables should not be separate — perhaps r,i,f could be combined? (I need to see
SHOW CREATE TABLE
to say more.)Do NOT have a commalist in
winner_id
. Instead have another table with one row per winner per game (or whatever it is a winner of). Perhaps just to columns like a Many-to-many mapping table.Noting that the execution is likely to start with
m
and then go next toi
let’s improve on Joel’s suggestion:Note that 3 tables are joined on
guild_id
; but only 2=
are needed.SUM
withoutGROUP BY
sums up the entire resultset (after JOINing). But you have 6 non-aggregates, so you need toGROUP BY
all 6.But that may lead to grossly inflated sums. Maybe you need to do the aggregation just over
f
first since that is where you are summing. Then JOIN to the rest??