2013-05-06 82 views
0

我真的停留在这个问题上。我需要创建一个查询,其中有一个包含CustomerID和PurchaseID号码的表。在另一张表中,我有CustomerID以及客户的名字和姓氏。我需要做的是只获取记录有PurchaseID为1或2或7的客户的姓氏和名字。当我尝试我的代码时,我从第二个tabel(包含FirstName,LastName,和CustomerID),这是不正确的。比较表格信息从另一个

这是我的代码:

SELECT FirstName, LastName 
    FROM Customer, Purchase 
WHERE Purchase.PurchaseID = '1' 
    OR Purchase.PurchaseID = '2' 
    OR Purchase.PurchaseID = '7' 
GROUP BY FirstName, LastName; 

我很新的SQL,并会真的在这里感谢帮助。

+0

Customer,Purchase表之间的关系是什么? – KuldipMCA 2013-05-06 07:14:38

回答

2
SELECT DISTINCT c.FirstName, c.LastName 
FROM Customer c 
JOIN Purchase p ON p.CustomerID = c.CustomerID 
WHERE p.PurchaseID IN ('1', '2', '7') 
ORDER BY c.LastName, c.FirstName 

UPDATE:为了响应@大卫阿尔德里奇的意见,我只是测试的SQL Server 2008 R2与最新的服务包两种形式(他和我的)。并且它们生成成本执行计划IDENTICAL。实际上,我的连接形式的逻辑读取次数略低(但当然可能随实际ID的选择而变化)

我对SQL Server示例数据库AdventureWorksDW2008运行了这两个查询(因为David提到“我曾在数据仓库”):

select distinct c.FirstName, c.LastName 
from dbo.FactInternetSales s 
join dbo.DimCustomer c on c.CustomerKey = s.CustomerKey 
where s.ProductKey IN (328, 333, 472) 

SELECT FirstName, 
     LastName 
FROM dbo.DimCustomer c 
where exists (
     select null 
     from dbo.FactInternetSales s 
     WHERE s.CustomerKey = c.CustomerKey and 
       s.ProductKey in (328, 333, 472)) 
+0

如果回答中不需要购买记录详细信息,那么简单的加入可能效率非常低,除非优化程序认识到,排除购买列和包含distinct后,允许查询在发现单个匹配产品时暂停每个客户。我不认为它会。 – 2013-05-06 07:25:15

+0

优化器非常好。我更喜欢让它做它的设计...... – 2013-05-06 07:26:21

+0

它肯定是,但它也很容易测试它是否实际上做了转型。这个查询的效率可能非常低,我认为编写一个语义正确的查询通常会更好,因为它不会太依赖于优化器。对不起,但我必须投票否决,因为我已经在数据仓库工作,与基于存在的方法相比,这将会非常低效。 – 2013-05-06 07:31:20

-1

的另一种方式,去无IN

SELECT DISTINCT c.FirstName, c.LastName 
FROM Customer c 
JOIN Purchase p ON p.CustomerID = c.CustomerID 
WHERE 
p.PurchaseID = '1' OR p.PurchaseID = '2' 
OR p.PurchaseID = '7' 
ORDER BY c.LastName, c.FirstName 
0

育有基本都加入。你试图做的是JOIN旧的ANSI SQL-89语法。但不建议这样做。

SELECT FirstName, LastName 
FROM Customer, Purchase 
WHERE Customer.CustomerID = Purchase.CustomerID 
AND (Purchase.PurchaseID = '1' OR Purchase.PurchaseID = '2' 
OR Purchase.PurchaseID = '7') 

正确的方法做的是在Mitchwheat提到回答

1

尝试此查询:

SELECT C.FirstName, C.LastName 
    FROM Customer C 
    JOIN Purchase P ON P.CustomerID = C.CustomerID 
WHERE P.PurchaseID IN ('1','2','7') 
GROUP BY C.FirstName, C.LastName 

入住这SQL Fiddle test code以防万一,以确保它的工作原理。相同的客户添加了几个购买,以确保不会重复的结果。感谢David Aldridge指出了这一点。

还有另外一种选择,使用EXISTS作为David提出的答案。如果你有大桌子可以工作,应该更有效率。使用该选项检查此其他SQL Fiddle test code。使用旧的ANSI-89 JOIN语法

避免使用JOIN更好的可读性:

FROM Customer, Purchase 
WHERE Purchase.PurchaseID = '1' 

检查Aaron Bertrands blog有关它的更多信息

+1

这不会为每个客户购买他们购买的这些类型的产品返回一行吗? – 2013-05-06 07:22:24

+0

如果你添加一个GROUP BY,它应该修复所有弹出的冗余名称。 – bloodstorm17 2013-05-06 07:24:26

+1

虽然这不会在语义上正确。不同的会更接近,但查询会查找客户购买的所有匹配产品的完整列表,然后基本丢弃它们。可能非常低效。 – 2013-05-06 07:27:23

0

如果你想检查是否存在购买的各种产品对于客户,则使用:

SELECT FirstName, 
     LastName 
FROM Customer 
where exists (
     select null 
     from Purchase 
     WHERE Purchase.customerID = customer.customerid and 
       Purchase.PurchaseID in ('1','2','7')) 

优化器只需要在购买表中找到一行就可以知道客户是 被包括。

+0

Yeap,它的工作原理,我不知道为什么downvote。这里是[sql小提琴测试](http://sqlfiddle.com/#!3/ab3bd/4) – Yaroslav 2013-05-06 07:40:32

+0

干杯。关于downvote,呃我不亲自带他们。 – 2013-05-06 09:11:12