2011-01-27 57 views
1

我敢肯定,这是一个非常简单的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秒执行)。我几乎肯定有一个非常简单的方法来提取子查询,所以我没有三重复或删除子查询完全取代它们,我只是不知道该怎么做。 :(从好的一面来看,这可能很容易得到某人的支持:)

在此先感谢。

+0

您使用的数据库是? – Dan 2011-01-27 16:24:09

回答

0

我不知道你使用的是什么数据库引擎,但是如果它功能强大,你可以创建临时/变量表。

我相信你已经注意到,你使用同样的选择3次,如果执行一次,可能会更有用,将结果保存到临时表并在使用后删除它。

1
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) 
+0

'NULL'比较比@ Dan的字段之间的比较会更快吗? – Matthew 2011-01-27 16:59:52

+0

@马修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

1
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); 
0

,会做最大性能提升的是有正确的索引。 您不会说如果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 
          )) 
0

这假定您在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会不会被计算两次。

相关问题