2009-08-17 40 views
2

最適化しようとしているSQLコードがあります。コードでは、実行するにはかなり高価なビューです。この質問のために、ExpensiveViewと呼んでみましょう。ビューの上には、2つのサブクエリを介してビューに自身を結合するクエリがあります。例えばSQLクエリのヘルプを最適化する

select v1.varCharCol1, v1.intCol, v2.intCol from (
    select someId, varCharCol1, intCol from ExpensiveView where rank=1 
) as v1 inner join (
    select someId, intCol from ExpensiveView where rank=2 
) as v2 on v1.someId = v2.someId 

例の結果セット:

some random string, 5, 10 
other random string, 15, 15 

これは動作しますが、それは私が二回ExpensiveViewから選択することが抱えているので、遅いです。私がしたいのは、一度だけExpensiveViewから選択するためにcase文を使用することです。例えば

select someId, 
    case when rank = 1 then intCol else 0 end as rank1IntCol, 
    case when rank = 2 then intCol else 0 end as rank2IntCol 
from ExpensiveView where rank in (1,2) 

私はその後、グループsomeIdことによって、上記の結果とは得ることができますほとんど最初のクエリと同じもの:

select sum(rank1IntCol), sum(rank2Intcol) 
from (*the above query*) SubQueryData 
group by someId 

問題がvarCharCol1であるIランクが1のときに取得する必要があります。ランクが2のときよりもランクが異なる場合、その列には異なる値が含まれるため、グループで使用することはできません。

クエリを最適化するソリューションは誰にもありますので、ExpensiveViewから一度だけ選択してvarcharデータを取得できますか?

ありがとうございます。

答えて

3

それは私達があなたのビュー定義が表示されていないので、推測するのは難しいのですが、これを試してみてください。

SELECT MIN(CASE rank WHEN 1 THEN v1.varCharCol1 ELSE NULL END), 
     SUM(CASE rank WHEN 1 THEN rank1IntCol ELSE 0 END), 
     SUM(CASE rank WHEN 2 THEN rank2IntCol ELSE 0 END) 
FROM query 
GROUP BY 
     someId 

(注)このようなクエリのため、ほとんどの場合、その:

SELECT * 
FROM mytable1 m1 
JOIN mytable1 m2 
ON  … 

SQL ServerオプティマイザEager Spool(一時的なインデックス)を作成します。これは後でJOINの条件を検索するために使用されるため、おそらくこれらのトリックは冗長です。 NULLがあるVARCHARに対してMINを使用する場合

+0

に分()またはMAXを使用して、NULL値は無視されますか? – bugfixr

+0

'@ Chu':はい。 – Quassnoi

+0

さて、私はこれを実装し、それは素晴らしい動作します!私の古いクエリは、515行を返して実行するのに6秒かかりました。ケースを使用すると、わずか数ミリ秒になります。 Eagar Spoolingについて...なぜか分かりませんが、SQL Serverは元のクエリでEager Spoolingを実行していないようです。おそらく、クエリが本当にサブクエリであるか、where句がそれを混乱させていたという事実と関係しています。 いずれにしても、チップをありがとう! – bugfixr

0
select someId, 
    case when rank = 1 then varCharCol1 else '_' as varCharCol1 
    case when rank = 1 then intCol else 0 end as rank1IntCol, 
    case when rank = 2 then intCol else 0 end as rank2IntCol 
from ExpensiveView where rank in (1,2) 

次いで囲みクエリ