2015-11-27 3 views
3

Я новичок в SQL, и у меня есть некоторые проблемы с этим запросом, который просто невозможно выполнить, потому что он слишком неэффективен. Вот это, он просто загружает в течение нескольких часовКак сделать мой запрос SELECT более эффективным?

SELECT my_db_client_total.email as EMAIL_TOTAL, 
    my_db_client_total.name, my_db_client_total.country 
    FROM my_db_client_total, my_db_client_pro 
     WHERE (my_db_client_total.email<>'') 
    AND (my_db_client_total.country = '120') 
    AND (my_db_client_total.email IN (SELECT my_db_client_pro.email 
    FROM my_db_client_pro)); 

Мои столы организованы таким образом (!):

Table 1 :  Table 2 : 
    email   email 
    name   name 
    country  country 

Цель запроса это, чтобы проверить свою базу данных и обрабатывать еще запрос, где я хочу выбрать email, name и country от Table 1, где table1.email нет в table2.

Извините за мой плохой английский, и для моего уровня, как я сказал ранее, я начинающий и самоучка.

Если кто-нибудь может мне помочь или хотя бы просветить меня, я буду так благодарен за ваше время.

EDIT: Я точно не знаю, но я работаю со столом, где есть 20 000+ строк.

+0

до голосования за хорошо представленное усмотрение вопроса –

+0

У вас есть какие-либо показатели по my_db_client_total? Если нет, то вы должны создать его по крайней мере и, возможно, (страна, адрес электронной почты, имя). –

+0

@Strawberry Я не вижу опечатки? – Martin

ответ

1

Это ваш запрос (фиксировано немного со столом псевдонимами):

SELECT ct.email as EMAIL_TOTAL, ct.name, ct.country 
FROM my_db_client_total ct 
WHERE (ct.email <> '') AND 
     (ct.country = 120) AND 
     (ct.email IN (SELECT my_db_client_pro.email FROM my_db_client_pro)); 

(Я предполагаю, что 120 действительно является целым числом.)

В старых версиях MySQL exists является более эффективным, чем in, так переписать запрос как:

SELECT ct.email as EMAIL_TOTAL, ct.name, ct.country 
FROM my_db_client_total ct 
WHERE (ct.email <> '') AND 
     (ct.country = 120) AND 
     EXISTS (SELECT 1 FROM my_db_client_pro cp WHERE cp.email = ct.email); 

Далее рассмотрим индексы. Для этого запроса, хорошие показатели являются:

create index idx_my_db_client_total_2 on my_db_client_total(country, email, name); 

create index idx_my_db_client_pro_email on my_db_client_pro(email); 
+0

получаю ошибку: создать индекс idx_my_db_total_2 на my_db_total (страна, адрес электронной почты, имя); MySQL: Документация # 1170 - BLOB/TEXT столбец «страна», используемый в ключевых спецификациях без длины ключа Мое поле - tinytext ... –

+0

@MaximeRogissart. , , 'BLOB/TEXT' на самом деле не подходит для любого из этих столбцов (' varchar() 'кажется вполне достаточным). Тем не менее, вы можете попробовать индексировать без оскорбительных столбцов или использовать длину ключа. –

0
SELECT my_db_client_total.email as EMAIL_TOTAL, 
    my_db_client_total.name, my_db_client_total.country 
FROM 
    my_db_client_total, 
WHERE (my_db_client_total.email <> '') 
AND (my_db_client_total.country = '120') 
AND (my_db_client_total.email not IN (SELECT my_db_client_pro.email 
    FROM my_db_client_pro)); 

В принципе получить все данные из таблицы и где условия получения адреса электронной почты, а не в таблице 2

1

Ваш вопрос заявляет, вы используете MySQL, так что это даст вам внутреннее (запись должна существовать в обеих таблицах) присоединиться.

SELECT my_db_client_total.email as EMAIL_TOTAL, my_db_client_total.name, my_db_client_total.country 
FROM my_db_client_total inner join my_db_client_pro on my_db_client_pro.email = my_db_client_total.email 
WHERE (my_db_client_total.email<>'') AND (my_db_client_total.country = '120'); 

Чтобы выбрать строку, которая не существует в другой таблице это сделать:

SELECT my_db_client_total.email as EMAIL_TOTAL, my_db_client_total.name, my_db_client_total.country 
FROM my_db_client_total LEFT OUTER JOIN my_db_client_pro on my_db_client_pro.email = my_db_client_total.email 
WHERE (my_db_client_total.email<>'') AND (my_db_client_total.country = '120') AND my_db_client_pro.email IS NULL; 
+0

Ударьте! Как я могу преобразовать это для своей конечной цели, которая является полной противоположностью запроса? Могу ли я просто изменить 'присоединиться my_db_client_pro на my_db_client_pro.email = my_db_client_total.email' 'к присоединиться my_db_client_pro на my_db_client_pro.email = my_db_client_total.email' –

+0

@MaximeRogissart, никакой что не работал бы - я обновил ответ –

0

Если соединить 2 таблицы, почему бы вам не использовать правую таблицу в запросе вместо того, чтобы подзапрос на нем?

Попробуйте (только присоединиться):

SELECT my_db_client_total.email as EMAIL_TOTAL, my_db_client_total.name, my_db_client_total.country 
    FROM my_db_client_total, my_db_client_pro 
WHERE my_db_client_total.email <> '' 
    AND my_db_client_total.country = '120' 
    AND my_db_client_total.email = my_db_client_pro.email; 

или это (только подзапрос):

SELECT my_db_client_total.email as EMAIL_TOTAL, my_db_client_total.name, my_db_client_total.country 
    FROM my_db_client_total 
WHERE my_db_client_total.email <> '' 
    AND my_db_client_total.country = '120' 
    AND my_db_client_total.email IN (SELECT my_db_client_pro.email FROM my_db_client_pro); 
Смежные вопросы