База MySQL
Три таблицы:
orders { OrderID — PK, ... }
items { OID — FK }
states { OID — FK }
Есть разные статусы заказов, которые хранятся в табличке states.
В табличке items — содержимое заказа.
Возникли трудности с запросом.
Нужно выбрать все заказы:
— у которых нет статусов { CLOSED, SENT }
— в содержании которых есть товары с определенной категорией (например category_id = 4) и для этих заказов нет статуса { PERIODIC }
Трудности в том, как мне анализировать содержимое заказа.
Вот пример.
Есть заказ. У него есть статус SENT. У него в содержании помимо прочего есть товары с категорией 4. У заказа нет статуса { PERIODIC } — его нужно выбрать.
Другой заказ. У него есть статус PERIODIC, есть содержимое с разными категориями (в том числе и 4). Но нет статусов { CLOSED, SENT } — надо выбрать
Третий заказ. У него только товары из категории 4. И нет статуса { PERIODIC } — надо выбрать.
Еще заказ. Есть товары где нет категории 4. И нет статусов CLOSED или SENT — тоже надо выбрать.
Вот. Если не очень понятно объяснил — попробую еще раз
Здравствуйте, Grog13, Вы писали:
G>Три таблицы:
G>orders { OrderID — PK, ... }
G>items { OID — FK }
G>states { OID — FK }
Не хватает как минимум еще одной таблицы, связывающей многие-ко-многим товары (items) и заказы (orders). Пусть будет orderitems( int order, int item )
G>Есть разные статусы заказов, которые хранятся в табличке states.
G>В табличке items — содержимое заказа.
G>Возникли трудности с запросом.
G>Нужно выбрать все заказы:
G>- у которых нет статусов { CLOSED, SENT }
G>- в содержании которых есть товары с определенной категорией (например category_id = 4) и для этих заказов нет статуса { PERIODIC }
Как-то так, наверное:
select o.* from orders o
inner join orderitems oi on oi.order = o.order
inner join items i on i.item = oi.item
where ( o.status <> CLOSED and o.status <> SENT ) or
( o.status <> PERIODIC and 4 not in
( select i2.category_id from items i2 inner join orderitems oi2 on oi2.item = i2.item inner join orders o2 on o2.order = oi2.order where o2.order = o.order ) )
Возможно, не совсем прав насчет использования o.order из внешнего запроса во внутреннем, но вроде должно работать.
Ну и надо учитывать, что этот запрос очень неоптимальный.
Первое, что приходит в голову по поводу оптимизации, это добавление избыточной колонки с консолидированной информацией о продуктах заказа. Если исключения по статусам касаются только категорий, то как раз подходит. Можно взять битовую строку, где одним битом обозначить наличие в заказе хотя бы одного товара с категорией, которая соответствует этому биту. Так в запросе надо будет немного пошаманить с битовыми операциями, и никаких вложенных селектов.
Здравствуйте, Grog13, Вы писали:
G>База MySQL
G>Три таблицы:
G>orders { OrderID — PK, ... }
G>items { OID — FK }
G>states { OID — FK }
G>Есть разные статусы заказов, которые хранятся в табличке states.
G>В табличке items — содержимое заказа.
G>Возникли трудности с запросом.
G>Нужно выбрать все заказы:
G>- у которых нет статусов { CLOSED, SENT }
G>- в содержании которых есть товары с определенной категорией (например category_id = 4) и для этих заказов нет статуса { PERIODIC }
select
from orders o
where not exists (select null
from states s2
where s2.oid = o.OrderID
and s2.status in ('CLOSED', 'SENT')
)
or (exists (select null
from items i2
where i2.oid = o.OrderID
and i2.category = 4
)
and not exists (select null
from states s2
where s2.oid = o.OrderID
and s2.status = 'PERIODIC'
)
)