I'm looking to speed up this query. At the moment it takes just over 20 seconds to execute which is terrible.
I can't find a way to remove the sub queries by using and JOIN functions.
SQL:
(
SELECT
`manual`.`id`,
`fname`,
`lname`,
`email`,
'' AS `company`,
'' AS `level`,
`completed_tests`.`assessment`,
'' AS `st_ref`,
'1' AS `manual`,
`completed_tests`.`percentage`,
'' AS `last_visit`,
'' AS `joined`
FROM
`manual`
LEFT JOIN `used_codes` ON `manual`.`id` = `used_codes`.`user` AND `used_codes`.`id` = (SELECT MAX(`id`) FROM `used_codes` WHERE `user` = `manual`.`id` AND `manual` = 1)
LEFT JOIN `vcode` ON `manual`.`vcode` = `vcode`.`id`
LEFT JOIN `groups` ON `vcode`.`group` = `groups`.`id`
LEFT JOIN `completed_tests` ON `manual`.`id` = `completed_tests`.`user` AND `completed_tests`.`id` = (SELECT MAX(`id`) FROM `completed_tests` WHERE `user` = `manual`.`id` AND `manual` = 1)
)
UNION ALL
(
SELECT
`users`.`id`,
`fname`,
`lname`,
`email`,
`company`,
`users`.`level`,
`completed_tests`.`assessment`,
`orders`.`st_ref`,
'0' AS `manual`,
`completed_tests`.`percentage`,
`last_visit`,
`joined`
FROM
`users`
LEFT JOIN `orders` ON `users`.`id` = `orders`.`user` AND `orders`.`id` = (SELECT MAX(`id`) FROM `orders` WHERE `status` = 3 AND `user` = `users`.`id`)
LEFT JOIN `used_codes` ON `users`.`id` = `used_codes`.`user` AND `used_codes`.`id` = (SELECT MAX(`id`) FROM `used_codes` WHERE `user` = `users`.`id` AND `manual` = 1)
LEFT JOIN `vcode` ON `used_codes`.`vcode` = `vcode`.`id`
LEFT JOIN `groups` ON `vcode`.`group` = `groups`.`id`
LEFT JOIN `completed_tests` ON `users`.`id` = `completed_tests`.`user` AND `completed_tests`.`id` = (SELECT MAX(`id`) FROM `completed_tests` WHERE `user` = `users`.`id` AND `manual` = 0)
)
ORDER BY `lname` ASC, `fname` ASC;
To give you an idea of the database structure, there are two main tables, one for users
and another for manual
. The other tables hold additional data and are linked with the users's ID and another field called manual
to see which database they belong in.
The problem I'm having is that I need the data of that user to show whether they have any additional data in the other tables or not. When I tested this using JOIN functions, the record would be removed from the results completely.
I think the main part of the query that need rewriting is the LEFT JOIN
s. I can't work out a way that does the same as this: LEFT JOIN orders ON users.id = orders.user AND orders.id = (SELECT MAX(id) FROM orders WHERE status = 3 AND user = users.id)