За последние 24 часа нас посетили 17968 программистов и 1611 роботов. Сейчас ищут 923 программиста ...

Не могу составить запрос

Тема в разделе "MySQL", создана пользователем hp_by, 16 май 2014.

  1. hp_by

    hp_by Новичок

    С нами с:
    16 май 2014
    Сообщения:
    5
    Симпатии:
    0
    есть 3 таблицы

    product:
    id_product name

    orders:
    id_order date

    product_in_order:
    id_product id_order

    Нужно получить список товаров, ни разу не проданных в течении определённого периода. Нет проблем получить список проданных, а вот как не проданных? Второй день голову ломаю.
     
  2. BaranPHP

    BaranPHP Новичок

    С нами с:
    24 янв 2014
    Сообщения:
    356
    Симпатии:
    0
    Получаешь ID всех проданных товаров. Допустим это будут (1, 8, 33)
    Потом выбираешь все товары с условием WHERE `id` != (1, 8, 33)
     
  3. hp_by

    hp_by Новичок

    С нами с:
    16 май 2014
    Сообщения:
    5
    Симпатии:
    0
    товаров десятки тысяч. имел ввиду: как это сделать одним запросом?
     
  4. BaranPHP

    BaranPHP Новичок

    С нами с:
    24 янв 2014
    Сообщения:
    356
    Симпатии:
    0
    Да хоть сотни тысяч, принцип один. Как ты это сделаешь одним запросом если тут перебирать надо. Либо двумя запросами, либо сложносочинённый запрос, что по моему мнению одно***ственно. Либо заведи в товарах колонку где будет отмечаться, продавался ли товар за определённый период(допустим `дата_последней_продажи`).
     
  5. hp_by

    hp_by Новичок

    С нами с:
    16 май 2014
    Сообщения:
    5
    Симпатии:
    0
    "что по моему мнению одно***ственно" - подобные операции должна выполнять СУБД.
    "заведи в товарах колонку" - зачем хранить избыточную информацию, если можно вычислить из имеющихся данных? да и периоды произвольные.
    если проданные одним запросом вытаскиваю за доли секунды, почему не проданные нельзя? просто решение в голову не приходит... точнее есть одно через подзапрос, но оно не оптимально - слишком долго.

    Вот пример получения проданных:
    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
     
  6. BaranPHP

    BaranPHP Новичок

    С нами с:
    24 янв 2014
    Сообщения:
    356
    Симпатии:
    0
    Так они и вытаскиваются быстро только потому что имеется запись о том что они проданы, если хочешь также быстро доставать не проданные заведи колонку `дата_последней_продажи`.
    И периоды тут любые можно задать будет. Каждый раз когда товар продаётся в БД создаётся запись, найди эту функцию и добавь в ней чтобы так-же апдейтилось поле `дата_последней_продажи` на текущую дату, и всё. Сможешь делать выборку быстро одним запросом, за любой заданный период.
     
  7. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    Код (Text):
    1. SELECT id_product FROM product WHERE id_product NOT IN (SELECT DISTINCT id_product FROM product_in_order)
    Правда запроса таки два ) В принципе должно быть нормально, особенно если индексы на месте.

    Добавлено спустя 2 минуты 41 секунду:
    Это пока у тебя записей пара сотен, пофиг как и что, а на сотнях тысяч принцип далеко не один. Узкие места начинают встречаться в самых неожиданных местах, а за вариант что предложил ты вообще по башке стучат ).
     
  8. hp_by

    hp_by Новичок

    С нами с:
    16 май 2014
    Сообщения:
    5
    Симпатии:
    0
    насколько я понимаю подзапрос будет выполнятся для каждой строки таблицы product. Нечто подобное я сделал - получается почти минута...
    угу

    Если мы объединяем таблицы через LEFT - то получаем в не проданных товарах null, но проблема в том, что WHERE применяется уже как фильтр к полной выборке где null нет.
     
  9. BaranPHP

    BaranPHP Новичок

    С нами с:
    24 янв 2014
    Сообщения:
    356
    Симпатии:
    0
    И чем вот это:
    отличается от:
    Ромыч ...... у меня нет слов

    Добавлено спустя 4 минуты 17 секунд:
    Принцип как раз один время выполнения разное, но от этого никуда не дется. Самый быстрый запрос для 100 записей останется самым быстрым и для миллиона записей.
     
  10. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    хм... пишу из головы потому могу ошибиться, но как то так можно попробовать:
    Код (Text):
    1. SELECT `product`.`id_product` FROM `product`
    2. 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 может жестко тормозить из за блокировок.
     
  11. hp_by

    hp_by Новичок

    С нами с:
    16 май 2014
    Сообщения:
    5
    Симпатии:
    0
    Всё было бы именно так, если бы не было выборки по временному периоду