Нужно объединить 2 таблицы с более чем 200К данных. Как подготовить запрос? - PullRequest
0 голосов
/ 27 октября 2011

Мне нужно объединить 2 таблицы, в которых в настоящее время содержится более 200К данных.У меня есть члены и стол заказов.Я хотел бы получить участников, которые ничего не заказывали.

Я пытался следовать SQL-запросам;

Структура (просто перечисление того, что мне нужно)

ORDERS                  MEMBERS
id                      id
member_id               fullName
                        email
                        landLine
                        cellPhone

Запрос1

$sql  = 'SELECT '.PREFIX.'members.fullName
           , '.PREFIX.'members.email
           , '.PREFIX.'members.landLine
           , '.PREFIX.'members.cellPhone, ';
$sql .= 'FROM '.PREFIX.'members';
$sql .= 'LEFT JOIN ';
$sql .= PREFIX.'orders';
$sql .= ' ON ';
$sql .= PREFIX.'members.id = '.PREFIX.'orders.member_id';
$sql .= ' WHERE '.PREFIX.'orders.member_id IS NULL LIMIT 50';

Запрос 2

$sql2  = 'select id, fullName, email, landLine, cellphone 
          from '.PREFIX.'members 
          where '.PREFIX.'members.id not in 
             (select member_id from '.PREFIX.'orders) 
          LIMIT 50';

Запрос 3

$sql3  = 'select id, fullName, email, landLine, cellphone 
          from '.PREFIX.'members m 
          where not exists 
            (select null from '.PREFIX.'orders o where s.members_id = o.id) 
          LIMIT 50';

Все 3 запроса до сих пор не работали.Прошло больше минуты, я все еще жду результатов.

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

Заранее благодарю за помощь.

Ответы [ 5 ]

2 голосов
/ 27 октября 2011

запрос никогда не будет работать, если вы сделаете SELECT a,b FROM cLEFT JOIN d без пробела.В противном случае запрос 1 должен быть в порядке, и, на мой взгляд, это лучший способ выразить его.

Что касается производительности, вы должны поставить индексы, как предложил Марко.Оптимизатор должен быть достаточно умен, чтобы выдавать один и тот же план для всех трех запросов.

1 голос
/ 27 октября 2011

Хорошо, вот оно. Удалите часть «IS NULL» в конце, чтобы вы могли видеть, что на самом деле происходит; это довольно просто, когда видишь это = -)

выберите * из членов, оставивших заявки на присоединение на members.id = orders.member_id, ГДЕ member_id IS NULL;

Примечание: я думаю, что вы должны изменить имя вашего столбца 'id' на 'order_id' в таблице заказов и столбец 'id' в таблице членов на 'member_id', чтобы избежать путаницы. Также не забудьте добавить индексы.

Я проверил это, используя вашу структуру таблицы и мои собственные значения. Возвращает Майкла Джордана и Барака Обаму, потому что у них не было заказов.

INSERT INTO orders (id, member_id) VALUES ('aa', '1');
INSERT INTO orders (id, member_id) VALUES ('bb', '1');
INSERT INTO orders (id, member_id) VALUES ('cc', '1');
INSERT INTO orders (id, member_id) VALUES ('dd', '1');
INSERT INTO orders (id, member_id) VALUES ('gg', '2');
INSERT INTO orders (id, member_id) VALUES ('hh', '2');
INSERT INTO orders (id, member_id) VALUES ('ii', '2');
INSERT INTO orders (id, member_id) VALUES ('xx', '3');
INSERT INTO orders (id, member_id) VALUES ('yy', '3');
INSERT INTO orders (id, member_id) VALUES ('zz', '3');

INSERT INTO members (id, fullName, email, landLine, cellPhone) VALUES ('1', 'John smith', 'bigboy@yahoo.com', '1234567890', '1234567890');
INSERT INTO members (id, fullName, email, landLine, cellPhone) VALUES ('2', 'Person B', 'asfsdf@yahoo.com', '1234567890', '1234567890');
INSERT INTO members (id, fullName, email, landLine, cellPhone) VALUES ('3', 'Tom Brady', 'efe@yahoo.com', '1234567890', '1234567890');
INSERT INTO members (id, fullName, email, landLine, cellPhone) VALUES ('4', 'Michael Jordan', 'etett@yahoo.com', '1234567890', '1234567890');
INSERT INTO members (id, fullName, email, landLine, cellPhone) VALUES ('5', 'Barack Obama', 'sdfasf@yahoo.com', '1234567890', '1234567890');
1 голос
/ 27 октября 2011

Я должен попробовать

SELECT id, fullName, email, landLine, cellphone 
FROM members
WHERE id NOT IN
    (SELECT DISTINCT member_id FROM orders)
LIMIT 50

Обязательно ставьте индексы на members.id и orders.member_id.

0 голосов
/ 27 октября 2011

Ваш первый запрос, кажется, в порядке.

Убедитесь:

1) что orders.member_id это fk to members.id 2) есть индекс на orders.member_id и members.id

Я также предлагаю вам выполнить запрос непосредственно на клиенте MySQL и оптимизировать его там, а затем попробовать с php. По крайней мере, при оптимизации вы убедитесь, что mysql - не узкое место, а что-то еще.

0 голосов
/ 27 октября 2011

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

То, что вы хотите сделать, - это левое соединение по идентификатору и порядку участника, и всякий раз, когда член имеет нулевое значение вИдентификатор столбца у них не существовал в другой таблице.Протестируйте запрос в MySQL, прежде чем делать это в PHP, чтобы увидеть, что происходит.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...