есть 3 таблицы product: id_product name orders: id_order date product_in_order: id_product id_order Нужно получить список товаров, ни разу не проданных в течении определённого периода. Нет проблем получить список проданных, а вот как не проданных? Второй день голову ломаю.
Получаешь ID всех проданных товаров. Допустим это будут (1, 8, 33) Потом выбираешь все товары с условием WHERE `id` != (1, 8, 33)
Да хоть сотни тысяч, принцип один. Как ты это сделаешь одним запросом если тут перебирать надо. Либо двумя запросами, либо сложносочинённый запрос, что по моему мнению одно***ственно. Либо заведи в товарах колонку где будет отмечаться, продавался ли товар за определённый период(допустим `дата_последней_продажи`).
"что по моему мнению одно***ственно" - подобные операции должна выполнять СУБД. "заведи в товарах колонку" - зачем хранить избыточную информацию, если можно вычислить из имеющихся данных? да и периоды произвольные. если проданные одним запросом вытаскиваю за доли секунды, почему не проданные нельзя? просто решение в голову не приходит... точнее есть одно через подзапрос, но оно не оптимально - слишком долго. Вот пример получения проданных: SELECT p.name FROM orders AS o INNER JOIN products_in_orders AS op ON o.id_order = op.id_order INNER JOIN pref_product AS p ON op.id_product = p.id_product WHERE o.date BETWEEN 11.10.13 AND 13.10.13 GROUP BY op.id_product
Так они и вытаскиваются быстро только потому что имеется запись о том что они проданы, если хочешь также быстро доставать не проданные заведи колонку `дата_последней_продажи`. И периоды тут любые можно задать будет. Каждый раз когда товар продаётся в БД создаётся запись, найди эту функцию и добавь в ней чтобы так-же апдейтилось поле `дата_последней_продажи` на текущую дату, и всё. Сможешь делать выборку быстро одним запросом, за любой заданный период.
Код (Text): SELECT id_product FROM product WHERE id_product NOT IN (SELECT DISTINCT id_product FROM product_in_order) Правда запроса таки два ) В принципе должно быть нормально, особенно если индексы на месте. Добавлено спустя 2 минуты 41 секунду: Это пока у тебя записей пара сотен, пофиг как и что, а на сотнях тысяч принцип далеко не один. Узкие места начинают встречаться в самых неожиданных местах, а за вариант что предложил ты вообще по башке стучат ).
насколько я понимаю подзапрос будет выполнятся для каждой строки таблицы product. Нечто подобное я сделал - получается почти минута... угу Если мы объединяем таблицы через LEFT - то получаем в не проданных товарах null, но проблема в том, что WHERE применяется уже как фильтр к полной выборке где null нет.
И чем вот это: отличается от: Ромыч ...... у меня нет слов Добавлено спустя 4 минуты 17 секунд: Принцип как раз один время выполнения разное, но от этого никуда не дется. Самый быстрый запрос для 100 записей останется самым быстрым и для миллиона записей.
хм... пишу из головы потому могу ошибиться, но как то так можно попробовать: Код (Text): SELECT `product`.`id_product` FROM `product` LEFT JOIN `product_in_order` ON `product`.`id_product` = `product_in_order`.`id_product` WHERE `product_in_order`.`id_order` IS NULL; Индексы все на месте? EXPLAIN на что-нибудь ругается? хех. уже попробовал ) Кусок бы записей на поиграться, глядишь ещё кто подтянется. Добавлено спустя 16 минут 41 секунду: Не пробовал отсюда 3 таблицу выкинуть? Либо засунуть её в подзапрос? Или тип БД, MyISAM может жестко тормозить из за блокировок.