I am trying to get data from multiple tables at once. In my old system I would make a query, get the data I needed, and then use it for the next query. I wanted to avoid making multiple queries so I combined them with joins:
SELECT `to`.`id` , `to`.`group`, `to`.`email`, `pTo`.`min_offer`, COUNT(`offerRes`.`id`), `settingsRes`.`email`
FROM `members` AS `to`
LEFT JOIN (
SELECT `id` , `min_offer`
FROM `profile`
) pTo ON pTo.id = to.id
LEFT JOIN (
SELECT `id`, `from`,`to`
FROM `offers`
) offerRes ON offerRes.from = ? && offerRes.to = to.id
LEFT JOIN (
SELECT `id`, `email`
FROM `user_settings`
) settingsRes ON settingsRes.id = to.id
WHERE to.id = ? LIMIT 1
I use the ID that is passed in (to.id) to obtain results from the profiles table and the offers table and the user settings table. These tables all have a PRIMARY id to which everything is mapped to. My PHP users prepared statements however I replaced the ? with hard values in PHPMyAdmin. My EXPLAIN is as follows:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY to const PRIMARY PRIMARY 4 const 1
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 45
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 1
1 PRIMARY <derived4> ALL NULL NULL NULL NULL 15
4 DERIVED user_settingsALL NULL NULL NULL NULL 15
3 DERIVED offers system NULL NULL NULL NULL 1
2 DERIVED profile ALL NULL NULL NULL NULL 45
Why is MySQL going through all 45 rows in the profile field when it can do a simple lookup as my query is based on the PRIMARY key id? Any way to make this more efficent? All I want is a table of the following:
id (from members) - this is optional as this is what is obtained from the user and passed in to SELECT against
group (from members) - corresponding to the id that is passed in
email (from members) - corresponding to the id that is passed in
min_offer (from profile) - also corresponding to the id that is passed in
NUM_ROWS(from offers) - number of rows corresponding to the id taht is passed in and another number that is also passed in. The offers table has a PRIMARY id but it is a different ID than what is passed in.
email (from user_settings) - corresponding to the id that is passed in
Because you’re joining to the results of sub-queries, which will include every record from the table:
Instead, join to the tables directly: