SQL查询仅在所有订单详细信息都在列表中时才带回所有订单

时间:2018-09-19 03:31:28

标签: sql-server

我有一个orders表,其中包含许多与问题无关的order特定信息。但是,我然后有了一个orderDetails foreign key的{​​{1}}表。在此(orders.id == orderDetails.orderId)中,客户可以选择订购多种口味的产品,每种口味在此表中都有一个新条目,该条目链接回到主orderDetails

我想做的是选择所有order中存在所有风味的orders。因此,如果一个order有苹果,桃子和橙子,而我查询了苹果和桃子,则它不会返回该顺序,因为我的查询中没有橙色。

我尝试过order等,但是我觉得解决该问题的唯一方法是循环每个订单并查看详细信息,但这效率极低。有什么想法吗?

subqueries

因此,如果我没有任何桃子存货,我想看看SELECT * FROM orders WHERE id IN (SELECT orderId FROM orderdetails WHERE flavor IN('apple', 'peach', 'orange')) AND isInvoiced = 1 AND isShipped = 0 AND isOnHold = 0 中不包含任何桃子:

orders

这里现有查询的问题是它返回所有内容,因为它只是说,肯定,您要苹果……请您要橙色,并且此SELECT * FROM orders WHERE id IN (SELECT orderId FROM orderdetails WHERE flavor IN ('apple', 'orange')) AND isInvoiced = 1 AND isShipped = 0 AND isOnHold = 0 包含那些,所以我将其返回。我需要它全部还是全部。

在真实的数据库中,口味是ID的,在此示例中,我只是对其进行了简化。

已请求数据库表...我将继续列出它们,因为它们确实存在。

order

再进行一次编辑,这是我最初的失败尝试:

orders
-------
id
isInvoiced
isShipped
isOnHold

orderDetails
------------
id
orderId
flavorId

ID的列表将根据库存中实际有什么口味而改变。

4 个答案:

答案 0 :(得分:0)

基本上,您只能在条件GROUP BY flavor的情况下HAVING COUNT(*) = 3。因此,将列出具有这三种风味的订单

select * 
from   orders o
where  exists
       (
           select x.flavor
           from   orderdetails x
           where  x.orderId = o.id
           and    x.flavor in ('apple', 'peach', 'orange')
           group by x.flavor
           having count(*) = 3
       ) 
and    isInvoiced = 1 
and    isShipped  = 0 
and    isOnHold   = 0

答案 1 :(得分:0)

您可以使用计数功能来确保代表所有风味。

select o.* 
from   orders o
inner join 
       (
           select orderId, count(*) as flavorCount
           from   orderdetails 
           where  flavor in ('apple', 'peach', 'orange')
           group by orderId
       ) as t1

on o.orderId = t1.orderId

and    isInvoiced = 1 
and    isShipped  = 0 
and    isOnHold   = 0
and     t1.falvourCount = 3;

答案 2 :(得分:0)

通过评论“ 我完全意识到,我遗漏了一个非常重要的部分,因为每个订单可能有一种或多种口味,而不必全部呈现。” << / p>


以下查询符合原始要求:“ 我想做的是选择所有包含所有口味的订单”和“ 我需要它全部还是全部。

一个订单中可能有多个项目涉及一种风味(例如,“苹果派”和“苹果蛋糕”),所以我建议您在Have子句中使用3个case表达式来防止这种情况,同时仍要实现您的目标:

select o.* 
from   orders as o
inner join (
           select orderId 
           from   orderdetails 
           group by orderId
           having sum(case when flavor = 'apple' then 1 else 0 end) > 0
           and sum(case when flavor = 'peach' then 1 else 0 end) > 0
           and sum(case when flavor = 'orange' then 1 else 0 end) > 0
       ) as od on o.id = od.orderid
where o.isInvoiced = 1 
and o.isShipped  = 0 
and o.isOnHold   = 0

请注意,inner join的使用将列出的订单限制为仅涉及所有3种口味的订单。

此查询在此处得到证明:http://rextester.com/AKMM54555

答案 3 :(得分:0)

如果您有缺货和有货的口味列表,那会更简单。 因此,例如,如果'peach'缺货,并且'apple'和'orange'缺货,则以下查询将生成仅具有'apple'或'orange'的订单:

   SELECT * FROM orders 
   WHERE
     id IN (SELECT id FROM orderdetails WHERE  flavor IN ('apple','orange')  ) -- in stock
   AND 
     id NOT IN (SELECT id FROM orderdetails WHERE  flavor   IN ('peach')  )  --out of stock

您怎么看?