Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Оптимизировать SQL-запрос
Форумы портала PHP.SU » PHP » SQL и Архитектура БД » Оптимизировать SQL-запрос

Страниц (1): [1]
 

1. Deonis - 21 Мая, 2014 - 17:24:01 - перейти к сообщению
Всем привет! Для упрощения, взял абстрактную задачу, аналогичную существующей.
1. Есть таблица с заказами, в которой каждый заказ привязан к менеджеру
2. Вторая таблица - содержит записи ID-заказа и ID-менеджера, которые должны игнорироваться.
Нужно: Выбрать из талицы заказов те записи, которые есть у определенного менеджера, но которых нет в таблице с игнорируемыми заказами у этого же менеджера.
Пример закинул в песочницу (url с хешем "режется" на форуме, посему ссылка TinyURL), где есть два менеджера и для первого (с ID = 1), есть два заказа, которые не должны учитываться при выборке.
На данный момент, есть запрос, который исправно работает, но хотелось бы оптимизировать:
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT * FROM `orders` WHERE `ord_id` NOT IN (
  2.   SELECT `o_id` FROM `ignore_orders` WHERE `m_id` = ?
  3. ) AND `manager_id` = ?
Где в плейсхолдер (?) подставляется ID менеджера.
Толи я не выспался, толи что-то у меня сегодня с руками, но через JOIN переделать запрос не получается. Буду признателен, если подтолкнете в нужном направлении.
2. EuGen - 21 Мая, 2014 - 17:31:34 - перейти к сообщению
Deonis пишет:
На данный момент, есть запрос, который исправно работает,

Если речь о MySQL, то, в случае, если подзапрос не является зависимым, начиная с версии 5.6 (возможно, даже 5.5) СУБД автоматически преобразует его в соответствующий JOIN.

Но если интерес чисто академический, то (если я правильно понял связь между таблицами)

CODE (SQL):
скопировать код в буфер обмена
  1. SELECT
  2.   `orders`.*
  3. FROM `orders`
  4.   LEFT JOIN `ignore_orders`
  5.     ON `orders`.`ord_id`=`ignore_orders`.`o_id`
  6. WHERE
  7.   `ignore_orders` .`id` IS NULL
  8.   AND
  9.   `orders`.`manager_id` = ?


Условие из подзапроса я убрал, предполагая, что m_id там - это то же самое manager_id во внешнем условии (то есть, так как мы делаем JOIN, это условие будет излишне). Поле id для таблицы ignore_orders "взято с потолка", это просто должно быть что-то, являющееся первичным ключом (чтобы можно было гарантировать, что наличие NULL для LEFT JOIN в этом поле означает отсутствие соответствующей записи)
3. Deonis - 21 Мая, 2014 - 17:37:21 - перейти к сообщению
EuGen пишет:
то есть, так как мы делаем JOIN, это условие будет излишне
Спасибо! Вот то, что я упустил из виду. А я дурень его лепил вторым условием в JOIN
EuGen пишет:
начиная с версии 5.6 (возможно, даже 5.5) СУБД автоматически преобразует его в соответствующий JOIN
За это отдельное спасибо, т.к. не знал Улыбка

 

Powered by ExBB FM 1.0 RC1