powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Помогите составить запрос к базе
20 сообщений из 20, страница 1 из 1
Помогите составить запрос к базе
    #39401434
deltaman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.
Есть база с данными о заказах и товарах в заказе. Задача - вывести емайл покупателя, который НЕ покупал определенный товар.

INSERT INTO `order` (`order_id`, `email`) VALUES
(1, 'mail1@domen.ru'),
(2, 'mail2@domen.ru');

INSERT INTO `order_product` (`order_product_id`, `product_id`, `order_id`) VALUES
(1, 1, 1),
(2, 2, 1),
(3, 3, 1),
(4, 4, 2),
(5, 5, 2),
(6, 6, 2);

Например, как найти email того, кто НЕ покупал товар с product_id = 5
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39401436
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"В лоб" - через NOT EXISTS.
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39401456
deltaman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
С NOT EXISTS боюсь что при больших объемах базы, а эти таблицы часто имеют десятки тысяч строк, будет очень тяжело и не оптимально.
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39401460
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
deltamanС NOT EXISTS боюсь что при больших объемах базы, а эти таблицы часто имеют десятки тысяч строк, будет очень тяжело и не оптимально.При наличии правильного индекса все будет хорошо.
И даже без него десятки тысяч записей - это весьма немного.
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39401488
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
SELECT o.email
FROM order o
LEFT JOIN order_product op 
  ON o.order_id = op.order_id AND op.product_id = 5
WHERE op.order_id IS NULL
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39401518
deltaman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кажется то что надо, спасибо!

Тогда, тот кто покупал, будет:
Код: sql
1.
op.order_id IS NOT NULL


правильно мыслю?
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39401623
deltaman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Подскажите, пожалуйста, а если будет еще одна таблица:

INSERT INTO `product_to_category` (`product_id`, `category_id`) VALUES
(1, 1),
(2, 2),
(3, 2),
(4, 1),
(5, 1),
(6, 2);

Как выбрать тех кто не покупал продукты из category_id = 2 ?
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39401666
paver
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
deltamanправильно мыслю?
Нет. INNER JOIN и без WHERE
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39401762
deltaman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ок, спасибо, подправил.
Для выборки того, кто покупал товары из категории 2 сделал так:
Код: sql
1.
2.
3.
4.
SELECT DISTINCT o.email 
FROM  `order` o 
INNER JOIN  `order_product` op ON (o.order_id = op.order_id) 
INNER JOIN  `product_to_category` p2c ON (op.product_id = p2c.product_id AND p2c.category_id = '2')


Вроде бы работает, правильно ли я составил запрос?

А вот выбрать кто не покупал что-то пока не получается.
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39401966
paver
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
deltaman,
насчет фильтра p2c.category_id = '2'
авторВ большинстве случаев не следует указывать в части ON какие бы то ни было условия, накладывающие ограничения на строки в наборе результатов (из этого правила есть исключения). Если необходимо указать, какие строки должны присутствовать в результате, следует сделать это в выражении WHERE.

авторА вот выбрать кто не покупал что-то пока не получается.

Принцип тот же, что и для 2х таблиц
авторЕсли запись для правой таблицы в частях ON или USING в LEFT JOIN не найдена, то для данной таблицы используется строка, в которой все столбцы установлены в NULL. Эту возможность можно применять для нахождения результатов в таблице, не имеющей эквивалента в другой таблице:
mysql> SELECT table1.* FROM table1
LEFT JOIN table2 ON table1.id=table2.id
WHERE table2.id IS NULL;

Этот пример находит все строки в таблице table1 с величиной id, которая не присутствует в таблице table2 (т.е. все строки в table1, для которых нет соответствующих строк в table2)
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39402074
deltaman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Появился один нюанс с первым вариантом:
Код: sql
1.
2.
3.
4.
5.
SELECT o.email
FROM order o
LEFT JOIN order_product op 
  ON o.order_id = op.order_id AND op.product_id = 5
WHERE op.order_id IS NULL


Если в таблице будет еще заказ того же человека, но без товара product_id=5 в заказе, то он тоже выведется, а этого не хочется.

То есть если имеем:
INSERT INTO `order` (`order_id`, `email`) VALUES
(1, 'mail1@domen.ru'),
(2, 'mail2@domen.ru'),
(3, 'mail2@domen.ru');

INSERT INTO `order_product` (`order_product_id`, `product_id`, `order_id`) VALUES
(1, 1, 1),
(2, 2, 1),
(3, 3, 1),
(4, 4, 2),
(5, 5, 2),
(6, 6, 2),
(7, 1, 3),
(8, 2, 3);

Как быть в таком случае, как найти того, кто точно не покупал product_id=5 ?
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39402145
deltaman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
У меня получились вот такие варианты:
Код: sql
1.
2.
3.
4.
SELECT DISTINCT o.email FROM `order` o 
LEFT JOIN  `order_product` op ON (o.order_id = op.order_id AND op.product_id = '5') 
LEFT JOIN (SELECT DISTINCT o2.email FROM  `order` o2 INNER JOIN `order_product` op2 ON (o2.order_id = op2.order_id) WHERE op2.product_id = '5') e2 ON (o.email = e2.email) 
WHERE op.order_id IS NULL AND o.email <> '' AND e2.email IS NULL


Код: sql
1.
2.
3.
4.
SELECT DISTINCT o.email FROM `order` o 
LEFT JOIN `order_product` op ON (o.order_id = op.order_id AND op.product_id = '5') 
WHERE op.order_id IS NULL AND o.email <> ''
AND o.email NOT IN (SELECT DISTINCT o2.email FROM `order` o2 INNER JOIN `order_product` op2 ON (o2.order_id = op2.order_id) WHERE op2.product_id = '5')



Склоняюсь к первому.
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39402304
paver
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: sql
1.
2.
3.
4.
5.
6.
7.
SELECT email
FROM  order
WHERE email NOT IN (
  SELECT DISTINCT o.email
  FROM order o
  JOIN order_product op ON o.order_id = op.order_id
  WHERE op.product_id = 5)
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39402571
deltaman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Не знаком с тонкостями SQL, поэтому возникает вопрос, будет ли в варианте с NOT IN делаться этот под-запрос для каждого email?
И как это скажется на производительности при 10к адресов?
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39402648
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
deltamanНе знаком с тонкостями SQL, поэтому возникает вопрос, будет ли в варианте с NOT IN делаться этот под-запрос для каждого email?
И как это скажется на производительности при 10к адресов?Зависит от версии MySQL.
В старых версиях, действительно, подзапрос выполнялся многократно. Начиная с версии 5.6 это поправили.
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39402669
deltaman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
авторНачиная с версии 5.6 это поправили.
У клиентов может быть что угодно, поэтому опасаюсь пока применять.

Допустимо ли использовать в этом случае мой вариант:
Код: sql
1.
2.
3.
4.
SELECT DISTINCT o.email FROM `order` o 
LEFT JOIN  `order_product` op ON (o.order_id = op.order_id AND op.product_id = '5') 
LEFT JOIN (SELECT DISTINCT o2.email FROM  `order` o2 INNER JOIN `order_product` op2 ON (o2.order_id = op2.order_id) WHERE op2.product_id = '5') e2 ON (o.email = e2.email) 
WHERE op.order_id IS NULL AND o.email <> '' AND e2.email IS NULL



Или он совсем плох?
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39403319
paver
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
deltaman,
Код: sql
1.
2.
3.
4.
5.
6.
SELECT o.email
FROM `order` AS o
LEFT JOIN order_product AS op
  ON o.order_id = op.order_id AND op.product_id = 5
GROUP BY o.email
HAVING max(op.order_id) IS NULL
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39403536
deltaman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо, но очень медленный, примерно в 7 раз медленнее моего варианта. (0.0008с/0.0059с) при (1к order и 17к order_product)
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39403868
paver
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
deltaman,
сомнительно как-то. А для измерения времени запрос сколько раз выполнили?
...
Рейтинг: 0 / 0
Помогите составить запрос к базе
    #39403884
deltaman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Каждый запрос выполнял строго по 1 разу, потом менял id продукта и снова проверял.
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Помогите составить запрос к базе
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]