SQL:如何根据订单详细信息提取特定订单?
我有四个表,即客户、订单、订单详情和产品 客户表SQL:如何根据订单详细信息提取特定订单?,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我有四个表,即客户、订单、订单详情和产品 客户表 cId cName 1 James 2 Adam 3 Ed 订单表 oId cId 1 1 2 2 3 3 OrderDetails表 oId odId pId Quantity 1 1 1 50 1 2 2 45 2 3 2 52 3 4 1 44 产品表 pId PName 1 Apple 2 Orange 我要一份从
cId cName
1 James
2 Adam
3 Ed
订单表
oId cId
1 1
2 2
3 3
OrderDetails表
oId odId pId Quantity
1 1 1 50
1 2 2 45
2 3 2 52
3 4 1 44
产品表
pId PName
1 Apple
2 Orange
我要一份从未点过橘子的顾客名单。我能够提取订单详细信息中没有橙子的客户的记录。但在其中一个案例中,詹姆斯同时点了苹果和桔子。因此,这个问题不应该牵扯到詹姆斯。我可以通过一个更大的查询来实现这一点。但我想用一个较小的查询来说明我遗漏了什么
SQL
使用
不存在
SELECT *
FROM Customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o
JOIN orderDetails od ON o.oId = od.oId
JOIN products p ON od.pId = p.pId
WHERE p.pName = 'oranges' AND c.cId = o.cId
)
使用
不存在
SELECT *
FROM Customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o
JOIN orderDetails od ON o.oId = od.oId
JOIN products p ON od.pId = p.pId
WHERE p.pName = 'oranges' AND c.cId = o.cId
)
我会使用
不存在:
with has_oranges as (
select o.*
from orders o join
orderlines ol
on o.oid = ol.oid
where ol.pid = 2
)
select c.*
from customers c
where not exists (select 1
from has_oranges ho
where ho.cid = c.cid
);
如果您想要客户信息,我看不出oid
与任何事情都有什么关系
注:
- CTE决定谁有橙子
- 您不需要
products
表,因为您使用的是pid
我会使用不存在的来执行此操作:
with has_oranges as (
select o.*
from orders o join
orderlines ol
on o.oid = ol.oid
where ol.pid = 2
)
select c.*
from customers c
where not exists (select 1
from has_oranges ho
where ho.cid = c.cid
);
如果您想要客户信息,我看不出oid
与任何事情都有什么关系
注:
- CTE决定谁有橙子
- 您不需要
products
表,因为您使用的是pid
这将退回未订购橙子的客户。
这是SQLFIDLE链接:
这将退回未订购橙子的客户。
这是sqlfiddle链接:您想要的是所有从未订购过橙子的客户。因此,选择订购橙子的所有客户ID,并仅显示不在此数据集中的客户
select *
from customers c
where cid not in
(
select cid
from orderdetails
where pid = (select pid from products where pname = 'Orange'
);
您希望所有从未订购过橙子的客户。因此,选择订购橙子的所有客户ID,并仅显示不在此数据集中的客户
select *
from customers c
where cid not in
(
select cid
from orderdetails
where pid = (select pid from products where pname = 'Orange'
);
SQLServer2008引入了EXCEPT和INTERSECT关键字来执行这类操作。我倾向于发现查询比使用CTE时更清晰
您可以通过在查询的后半部分连接到Customer表,将名称添加到结果集中:
select c.cId, c.cName
from Customer c
except
select o.cId, c.cName
from Orders o
join OrderDetail od on o.oId = od.oId
join Customer c on c.cId = o.cId
and od.pId = 2
cId cName
----------- --------------------
3 Ed
SQLServer2008引入了EXCEPT和INTERSECT关键字来执行这类操作。我倾向于发现查询比使用CTE时更清晰
您可以通过在查询的后半部分连接到Customer表,将名称添加到结果集中:
select c.cId, c.cName
from Customer c
except
select o.cId, c.cName
from Orders o
join OrderDetail od on o.oId = od.oId
join Customer c on c.cId = o.cId
and od.pId = 2
cId cName
----------- --------------------
3 Ed
我们必须排除那些使用橙色的用户。所以在下面的查询中,我使用了子查询
Select C.Cname,OH.oid,PM.Pname,OD.Quantity from Customers C
inner join OrderHeader OH ON C.cid=OH.Cid
inner join OrderDetails OD on oh.oid=od.oid
inner join ProductMast PM on PM.pid=OD.pid where OH.oid not in (select oid
from OrderDetails where pid = 2)
我们必须排除那些使用橙色的用户。所以在下面的查询中,我使用了子查询
Select C.Cname,OH.oid,PM.Pname,OD.Quantity from Customers C
inner join OrderHeader OH ON C.cid=OH.Cid
inner join OrderDetails OD on oh.oid=od.oid
inner join ProductMast PM on PM.pid=OD.pid where OH.oid not in (select oid
from OrderDetails where pid = 2)
WHERE子句使第二个左连接作为常规内部连接。WHERE子句使第二个左连接作为常规内部连接。我收到一个错误。我认为这里显式连接优先于隐式连接。您的SQL正在提取customers表的所有记录。(相当于“从客户中选择*”)@madhukar my query相当于您接受的Gordon Linoff解决方案。您可能没有订购“橙子”的客户。将p.pName='oranges'
替换为ol.pid=2
,是否正常?是。如果我将名称替换为Id,它将起作用。Thanks@Madhukar好的,好的。我有一个错误。我认为这里显式连接优先于隐式连接。您的SQL正在提取customers表的所有记录。(相当于“从客户中选择*”)@madhukar my query相当于您接受的Gordon Linoff解决方案。您可能没有订购“橙子”的客户。将p.pName='oranges'
替换为ol.pid=2
,是否正常?是。如果我将名称替换为Id,它将起作用。Thanks@Madhukar好的,很好。工作!谢谢你的工作!非常感谢。