简体   繁体   中英

SQL Query Multiple Products on One Order

Let's say I have 2 tables:

tOrder               tOrderLine
------               ----------
OrderID              OrderID
Other Fields         ProductID
                     Other Fields

I want to get back all orders that have a certain 2 products on the same order. Currently, I'm doing:

select o.OrderID
from tOrder o
     inner join tOrderLine ol on o.OrderID = ol.OrderID
     inner join tOrderLine ol2 on o.OrderID = ol2.OrderID
where ol.ProductID = 67
     and ol2.ProductID = 68

This works and gives me the results I need, but it seems a little hokey. Also, if I wanted to get all orders that have a set of 10 items, the query is going to get monstrous.

Is there a better way to do what I'm looking for?

You could try to solve it using a distinct count on a having :

select t.OrderId
,      count(*)
from   tOrder t
join   tOrderLine o
on     t.OrderID = o.OrderID
where  o.ProductId in (67, 68)
group
by     t.OrderId
having count(distinct o.ProductId) = 2

There are 2 simple ways I can think to do it:

  1. Inner join to tOrderLine twice. Exactly how you did it. I actually would have never thought of that. It was an interesting solution when I saw it.
  2. EXISTS clauses. For each tOrder row, check if there exists a row in tOrderLine corresponding to it and one of the products.

For example:

select tOrder.OrderID
from tOrder o
where exists (select 1 from tOrderLine ol where ol.OrderID = o.OrderID and ol.ProductID = 67)
  and exists (select 1 from tOrderLine ol where ol.OrderID = o.OrderID and ol.ProductID = 68)

This is how I would write it, simply because it's more obvious what the query is doing. On the other hand, yours seems easier for the parser to optimize.

I'd be curious to know if you look at the execution plan of either one if they are the same. The correlated sub-queries could be rewritten internally to be inner joins.

Try this

Select Distinct a.*
From tOrder a
inner join tOrderLine b on a.orderId = b.orderId
Where a.orderId in
(
  Select orderId
  From tOrderLine
  Where 
  productId in (68,69)
  --replace with set of products you want
  Group by orderId
  Having Count(Distinct productId) = 2 
  ---replace with 10 if you want to return orders with 10 items
 )

SQL DEMO

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM