У меня был скрипт, используемый для получения данных, связанных со счетами от клиентов. Каждый счет и заказ имеют код карты, связывающий его с конкретным пользователем. Иногда у пользователей было несколько учетных записей, связанных с одним и тем же кодом карты; в таких обстоятельствах мне придется использовать данные пользователя из последней использованной учетной записи пользователя, которые я получу с помощью подзапроса.
SELECT invoices.*,card.*,client.*
FROM `orders`
LEFT JOIN `invoices` ON `invoices`.`invoice_key` =`orders`.`invoice_key`
LEFT JOIN `cards` `card` ON `card`.`card_code` = `orders`.`card_code`
LEFT JOIN `users` `client` ON `client`.`id` = (
SELECT MIN(c.id) c_id FROM `users` `c`
WHERE (`card`.`card_code` COLLATE utf8_unicode_ci) = `c`.`card_code`
AND `c`.`active` = 1 ORDER BY `c`.`last_login` DESC LIMIT 1
)
WHERE `orders`.`date` BETWEEN %start_date% AND %end_date%
Это работало нормально, но затем я внедрил систему, в которой для пользователя было возможно иметь несколько карточных кодов; Чтобы справиться с этим, я создал еще одну таблицу (пользовательские карты), которая связывает пользователей с картами. Не у всех пользователей есть запись здесь; большинству нужен только код карты по умолчанию.
SELECT invoices.*,card.*,client.*
FROM `orders`
LEFT JOIN `invoices` ON `invoices`.`invoice_key` =`orders`.`invoice_key`
LEFT JOIN `cards` `card` ON `card`.`card_code` = `orders`.`card_code`
LEFT JOIN `usercards` ON `usercards`.`card_code` = `card`.`card_code`
LEFT JOIN `users` `client` ON (`usercards`.`user_id` IS NOT NULL
AND `client`.`id` = `usercards`.`user_id`)
OR (`usercards`.`user_id` IS NULL AND `client`.`id` = (
SELECT MIN(c.id) c_id FROM `users` `c`
WHERE (`card`.`card_code` COLLATE utf8_unicode_ci) = `c`.`card_code`
AND `c`.`active` = 1 ORDER BY `c`.`last_login` DESC LIMIT 1)
)
WHERE `orders`.`date` BETWEEN %start_date% AND %end_date%
Однако, это привело к тому, что запрос выполнялся на намного медленнее - как несколько минут, когда раньше он был меньше секунды. Я знаю, что это как-то связано с подзапросом (если я пропускаю эту часть и просто присоединяюсь везде, где client.card_code = card.card_code, это работает быстро, но, конечно, тогда данные неверны), но я не могу понять, почему? Я не вижу ни одной точки, которая предполагает экспоненциальное увеличение данных, которые необходимо обработать.
Существует много заказов и счетов, но только несколько записей в карточках пользователей. Кроме того, usercards.card_code - это уникальный индекс.