мне нужно оптимизировать запрос, в котором присоединиться зависит от состоянияКак оптимизировать запрос с условным соединением?
У меня есть две таблицы
Table1 имеет две колонки, назовём их А и столбцы B, которые могут коснуться столбца table2 C,
если столбец B имеет нулевое значение, я должен соответствовать T1.a с t2.C если столбец B не равно нулю, я должен соответствовать T1.b с t2.C
и, наконец, я должен знать, какие записи на t1 не соответствуют по t2 ...
Чтобы предоставить более подробную информацию, t1 представляет собой таблицу клиентов, и оба A и B являются клиентскими кодами. Коды никогда не совпадают с кодами B, а в случаях, когда существует B, B имеет приоритет (B - это новый клиентский код, но старые клиенты его не имеют. В случае, когда B является нулевым, A является код для использования) (все это, потому что столбец B является новым, а старые клиенты имеют нулевые значения для B).
t2 - таблица покупок. t2.C - это клиентский код, но в этом случае это один столбец, он хранит коды для старых клиентов и коды B для новых клиентов.
Единственное, что я хочу, это знать, у каких клиентов пока нет покупок, с максимально эффективным запросом.
Я придумал несколько запросов, но они очень медленно, я думаю, из-за того, как обрабатывается условие:
Первая попытка:
select *
from t1
left join t2 on (t1.A = t2.C or t1.B = t2.C)
where t2.D is null;
Обратите внимание, что я могу использовать OR потому что я ЗНАЮ, что t1.A никогда не будет таким же, как любой t1.B, поэтому в t2.C, он coult будет соответствовать только A или B, но никогда не будет (предположим, что условие гарантировано). Запрос настолько медленный, что он был отключен в моем SQL-клиенте.
Вторая попытка
select *
from t1
left join t2 on (if(t1.B is null, t1.A = t2.C, t1.B = t2.C))
where t2.D is null;
В этом случае условие Comparision зависит от T1.b, если равно нулю, он сравнивает с A, и если это не так, с Б. Снова запрос крайне медленно ,
Я думаю, я мог бы использовать только два соединения и использовать каждое условие (A или B) для каждого соединения, но я точно не знаю, как его достичь, особенно потому, что мне нужно получить только те случаи, когда ни один A o B имеют совпадение по t2. (т. е. клиенты t1 без покупки t2)
Каковы мои возможности для создания более эффективных запросов для такого случая?
Благодаря
спасибо! первая версия (с 'ifnull') работает очень хорошо, то, что я вижу, очень похоже на мою вторую попытку, в которой я использую' on (if (t1.B is null, t1.A = t2.C, t1.B = t2.C)) 'вместо вашего' on ifnull (t1.B, t1.A) = t2.C'. Что делает их настолько разными, что ваша версия более эффективна, чем моя? Я нахожу это действительно интересным. И действительно, ваша версия ifnull работает быстрее, чем объединение всех (.2 против 6 секунд), несмотря на то, что у меня есть индексы для всех задействованных столбцов (A, B и C). – DiegoDD
Причина 'IFNULL' работает лучше, чем ваш оператор if, потому что столбец' t2.C' не содержится в нем, он статичен, поэтому MySQL знает, что он может использовать индекс в этом столбце, тогда как в вашем if-заявлении он не может работать, что 't2.C' используется как в истинном, так и в ложном выражениях, поэтому он не использует индекс. – GarethD
О, теперь я понял! поэтому это происходит не из-за просто использования 'ifnull (x, y)' вместо 'if (x is null, y, x)', а потому, что столбец сравнения находится за пределами 'if'. Поэтому, используя '(if (t1.B is null, t1.A, t1.B) = t2.C)' - это то же самое, что и с ifnull(). Благодаря! – DiegoDD