2017-11-30 11 views
0

私は非常にslooowwwwwクエリを持っています。SQL Serverサブクエリを使用するクエリが遅い

それはちょっと、このように、複合基準で、顧客レコードを選択:

表はCustomersを持って、別のテーブルには、別のテーブルにはCustomerMotorcyclesを持って、CustomerCarsを持っています。

お客様は1台以上の車を所有できます。顧客が商用ビジネスであり、顧客の車のいずれかがフォードである場合、その顧客を選択から除外したい。

顧客は1つ以上のオートバイを所有することもできます。お客様が小売業で、オートバイのいずれかがハーレーの場合、その顧客を除外します。

だから私はのような文があります。

SELECT * 
FROM CUST 
WHERE 
    (CUST.CUSTTYPE = 'COMM' 
    AND CUST.CUSTID NOT IN (SELECT CUSTCARS.CUSTID 
          FROM CUSTCARS 
          WHERE CUSTCARS.CAR = 'FORD')) 
    OR 
    (CUST.CUSTTYPE = 'RETAIL' 
    AND CUST.CUSTID NOT IN (SELECT CUSTCYCLES.CUSTID 
          FROM CUSTCYCLES 
          WHERE CUSTCYCLES.CYCLE = 'HARLEY')) 

をこれが遅いクレイジー実行されます。

これは現在、一時テーブルにデータをダンプし、不要なレコードを削除するためにいくつかの他のクエリが実行される一連の個別のクエリとして実行されていますが、非常に面倒です。

提案がありますか?助けてくれてありがとう!

+2

を我々は、nよテーブルとインデックスの詳細、および低速クエリのクエリプランを使用して、正確なアドバイスを提供することができます。 –

+0

exは簡略化され、すべてを書き出すには多くの時間がかかります...フィールドはnvarcharsでインデックスされています。 より良い構文があるのでしょうか。 JOINはWHERE節より優れていますか?そして、私はcase文を試しました。 TYPE = 'COMM'、CAR = 'FORD' N 'THERM'TYPE = 'RETAIL'そしてCYCLE = 'HARLEY' 'THEN' N 'の場合 ELSE' Y ' END AS KEEP それからKEEP = 'Y' しかし、これは正しいレコードを除外していませんでした。顧客がフォードとシェビーを抱えていた場合、彼は1つのレコードがフォードではなかったので選択されました...しかし、他のどの車種であっても、フォードを持っている人はいません。 –

答えて

1

我々は、我々が望んでいない条件に合致するデータを結合左、その後、where句によって一致する行を除外した場合、「左を除く参加する」試してみてください:私は「なくなり

SELECT 
     CUST.* 
FROM CUST 
LEFT JOIN CUSTCARS ON CUST.CUSTID = CUSTCARS.CUSTID 
     AND CUSTCARS.CAR = 'FORD' 
     AND CUST.CUSTTYPE = 'COMM' 
LEFT JOIN CUSTCYCLES ON CUST.CUSTID = CUSTCYCLES.CUSTID 
     AND CUSTCYCLES.CYCLE = 'HARLEY' 
     AND CUST.CUSTTYPE = 'RETAIL' 
WHERE CUSTCARS.CUSTID IS NULL 
OR CUSTCYCLES.CUSTID IS NULL 
; 

ここで、mは、それが役立つだろうので、おそらく1つのリストに2つのサブクエリを組み合わせOR(多分)過度の遅さの原因となる既存のクエリでは次のようになります。

SELECT 
     * 
FROM CUST 
WHERE CUSTID NOT IN (
     SELECT 
      CUSTCARS.CUSTID 
     FROM CUSTCARS 
     INNER JOIN CUST ON CUSTCARS.CUSTID = CUST.CUSTID 
     WHERE CUSTCARS.CAR = 'FORD' 
     AND CUST.CUSTTYPE = 'COMM' 
     UNION ALL 
     SELECT 
      CUSTCYCLES.CUSTID 
     FROM CUSTCYCLES 
     INNER JOIN CUST ON CUSTCYCLES.CUSTID = CUST.CUSTID 
     WHERE CUSTCYCLES.CYCLE = 'HARLEY' 
     AND CUST.CUSTTYPE = 'RETAIL' 
    ) 
; 
+0

ありがとう、私はあなたの提案をお試しください! –

+0

ありがとうございます。どちらのオプションを使用しましたか? –

0

私はnot existsで始まることをお勧め:次に

select c.* 
from cust c 
where not (c.custtype = 'COMM' and 
      exists (select 1 
        from custcars cc 
        where cc.custid =c.custid and cc.car = 'FORD' 
       ) 
     ) and 
     not (c.custtype = 'RETAIL' and 
      exists (select 1 
        from custcycles cc 
        where cc.custid = c.custid and cc.cycle = 'HARLEY' 
       ) 
     ) ; 

、あなたはcustcar(custid, car)custcycles(custid, cycle)のインデックスを持っていることを確認したいです。

+0

こんにちはゴードン! 私はこれを試しましたが、それは適切な顧客を排除していません。 私は得意先111のための3つのレコードが、たとえば、自分の車のいずれかがフォードですが、存在する場合、それはのように思える場合、それは顧客を除外する必要があります。 111フォード 111シボレー 111トヨタ これは、得意先111を除いていません 私は をしようとした場合は、私が(値1の)2つのレコード –

+0

@BrianBattlesを取得CC.CUSTID = 111 CUSTCARS CCから1を選択し、CC.CAR = FORD 。 。 。私はあなたが意味するものを正確に見ます。私はその論理を修正した。 –

0

2つのことが思い浮かびます。まず、CUSTCARS.CARおよびCUSTCYCLES.CYCLEの索引があることを確認します。次に、NOT INの代わりにNOT EXISTSを試してみてください。

SELECT * FROM CUST 
WHERE 
(CUST.CUSTTYPE = 'COMM' 
AND NOT EXISTS(SELECT 1 FROM CUSTCARS WHERE CUSTCARS.CAR = 'FORD' 
       AND CUSTCARS.CUSTID=CUST.CUSTID)) 

OR 

(CUST.CUSTTYPE = 'RETAIL' 
AND NOT EXISTS(SELECT 1 FROM CUSTCYCLES WHERE CUSTCYCLES.CYCLE = 'HARLEY' 
       AND CUSTCYCLES.CUSTID=CUST.CUSTID)) 
+0

ゴードンは私にそれを打つ... –

+0

私は見た;感謝ネイト...偉大な心は似て考える! –

関連する問題