найти продукты, которые не заказаны в определенном месяце

#sql #postgresql

#sql #postgresql

Вопрос:

я хочу найти продукты, у которых нет заказов в определенном месяце

у меня здесь три таблицы products, productorder, orderitems

 Products 
id | name |  price 

ProductOrder 
id | total_amount | order_date

OrderItems
id| product_id | order_id
 

это запрос, который я пробовал

 select * from products p 

left join orderitems oi on oi.product_id = p.id 

left join productorder po on oi.order_id= po.id 

where extract('month' from po.order_date) = 1 

and po.id is null
 

но это дает результат empyt.. Итак, как я могу найти результаты

Ответ №1:

Это звучит как not exists :

 select p.*
from products p
where not exists (select 1
                  from productorder po join
                       orderitems oi
                       on oi.order_id = po.id
                  where oi.product_id = p.id and
                        po.order_date >= '2020-12-01' and
                        po.order_date < '2021-01-01'
                 );
 

Комментарии:

1. извините, я не силен в sql .. я думал, что использование объединений более эффективно, чем подзапрос.. итак, я искал решение, которое использует объединения вместо подзапроса… Позвольте мне спросить вас об одном, почему мы не можем решить это с помощью объединений … если вы не возражаете, не могли бы вы уточнить…

2. @tstudent . . Вы можете решить это с помощью объединений (как показывают другие ответы). В большинстве баз данных left join и not exists будут иметь аналогичную производительность. in часто имеет худшую производительность.

Ответ №2:

Вы почти на месте. Просто используйте условие extract('month' from po.order_date) = 1 в LEFT JOIN следующем:

 select * 
  from products p 
  left join orderitems oi on oi.product_id = p.id 
  left join productorder po on oi.order_id= po.id 
                            and extract('month' from po.order_date) = 1
 where oi.id is null;
 

Кроме того, как упоминалось в ответе Гордона, лучше использовать dates extract функцию, а не.

— обновить

 select * 
  from products p 
  left join 
    (select oi.product_id 
       from orderitems oi
       join productorder po on oi.order_id= po.id 
                           and extract('month' from po.order_date) = 1) oi
     On p.id = oi.product_id
  where oi.product_id is null;
 

Комментарии:

1. большое спасибо @popeye за вашу поддержку.. у меня есть один запрос, почему «где извлечь (‘month’ из po.order_date) = 1 и po.id is null » также не работает из вашего ответа po.id не работает и oi.id is null работает . почему так .. если вы не возражаете, не могли бы вы объяснить….

Ответ №3:

Что-то подобное сработало бы:

 select * from products p 
where p.id NOT IN (
  select oi.product_id from orderitems oi
  inner join productorder po on oi.order_id= po.id
  where date_part('month', po.order_date) = 1
)
 

Вы можете проверить простой пример в SQLFiddle.

Выше будут получены идентификаторы продуктов, которые не были проданы в первый месяц 2020 года. Это делается с помощью NOT IN()... и путем выбора всех идентификаторов продуктов, у которых были продажи в этом месяце, в подзапросе.

Комментарии:

1. что эффективно с помощью join или нет в