如何在没有子查询的情况下在SQL中执行多个成员资格测试?
我敢肯定,这是一个非常简单的SQL问题,但我担心我的SQL-fu仍然无法帮助我解决问题。如何在没有子查询的情况下在SQL中执行多个成员资格测试?
我有一张销售订单和客户表。每个销售订单都有一个客户账户的ID号码和一个客户的ID号码(他们可能是一样的,但通常不是) - 之间存在一对多的关系一个“账单”和“船到”[例如,假设我向谷歌出售东西,“账单”将是谷歌的山景总部,但“船到”可能是谷歌的日内瓦办事处。)
所以我有一个基本上询问以下问题的查询: “给我销售订单表中的总销售额,其中此客户的Bill To与John Doe关联,或者此客户的Ship To与John Doe关联,但不包含该法案也是如此。“
和查询我已经是相当简单(读:幼稚)
SELECT SUM(price) FROM salesOrders
WHERE
(
(salesOrders.BillTo IN (SELECT customerID FROM customers WHERE customers.salesman = 'JOHNDOE')
OR
(salesOrders.ShipTo IN (SELECT customerID FROM customers WHERE customers.salesman = 'JOHNDOE')
AND
salesOrders.BillTo NOT IN (SELECT customerID FROM customers WHERE customers.salesman = 'JOHNDOE')
)
)
查询工作,但它只是需要的时间太长(〜6秒执行)。我几乎肯定有一个非常简单的方法来提取子查询,所以我没有三重复或删除子查询完全取代它们,我只是不知道该怎么做。 :(从好的一面来看,这可能很容易得到某人的支持:)
在此先感谢。
我不知道你使用的是什么数据库引擎,但是如果它功能强大,你可以创建临时/变量表。
我相信你已经注意到,你使用同样的选择3次,如果执行一次,可能会更有用,将结果保存到临时表并在使用后删除它。
SELECT SUM(so.price)
FROM salesOrders so
LEFT JOIN customers c1
on so.BillTo = c1.customerID
and c1.salesman = 'JOHNDOE'
LEFT JOIN customers c2
on so.ShipTo = c2.customerID
and c2.salesman = 'JOHNDOE'
WHERE c1.customerID IS NOT NULL
OR (c2.customerID IS NOT NULL AND c1.customerID IS NULL)
'NULL'比较比@ Dan的字段之间的比较会更快吗? – Matthew 2011-01-27 16:59:52
@马修PK:很难说没有看到真实的数据,但我担心[丹的答案](http://stackoverflow.com/questions/4818855/how-can-you-do-multiple-membership- tests-in-sql-without-subqueries/4819007#4819007)可能会返回不正确的结果。在我看来,'JOHNDOE'可能是BillTo和ShipTo账户的推销员,即使他们的ID(BillTo,ShipTo)不同。 – 2011-01-27 17:06:22
SELECT sum(s.price)
FROM salesOrders s
inner join customers bt on s.billto = bt.customerID
inner join customers st on s.ShipTo = st.customerID
WHERE
s.billto <> s.shipto and 'JONHDOE' in (bt.salesman, st.salesman);
,会做最大性能提升的是有正确的索引。 您不会说如果SQL 2008运行在哪个SQL Server上,它会在查看查询计划时为您提供要添加的索引提示。
我更喜欢使用存在,没有太多的使用它的性能增益,据我所知。你应该看看查询计划来检查。
SELECT SUM(price) FROM salesOrders
WHERE
EXISTS (SELECT * FROM customers WHERE
customers.salesman = 'JOHNDOE'
and ((salesOrders.ShipTo = customers.CustomerId
and not salesOrders.BillTo = customers.CustomerId)
or salesOrders.BillTo = customers.CustomerId
))
这假定您在salesOrders
有一个id列(S)(这里简称就像ID
):
SELECT SUM(s.Price)
FROM (
SELECT ID, Price, ShipTo AS CustomerID FROM salesOrders
UNION
SELECT ID, Price, BillTo FROM salesOrders
) s
INNER JOIN customers c ON s.CustomerID = c.CustomerID
WHERE c.salesman = 'JOHNDOE'
UNION消除重复的,所以情况BillTo
是相同的ShipTo
会不会被计算两次。
您使用的数据库是? – Dan 2011-01-27 16:24:09