2011-12-30 10 views
0

以下のSQLクエリ(SQL Server 2008)を改善するにはどうすればよいですか?私は、サブ選択を避けるために試してみたい、と私はこれは、ハード、同じデータなしでテストするために働くことがあり、この副選択クエリの改善

StateId  TotalCount  SFRCount  OtherCount 
--------------------------------------------------------- 
AZ    102    50    52 
CA    2931   2750   181 
etc... 

SELECT 
    StateId, 
    COUNT(*) AS TotalCount, 
    (SELECT COUNT(*) AS Expr1 FROM Property AS P2 
     WHERE (PropertyTypeId = 1) AND (StateId = P.StateId)) AS SFRCount, 
    (SELECT COUNT(*) AS Expr1 FROM Property AS P3 
     WHERE (PropertyTypeId <> 1) AND (StateId = P.StateId)) AS OtherCount 
FROM Property AS P 
GROUP BY StateId 
HAVING (COUNT(*) > 99) 
ORDER BY StateId 

答えて

10

のような結果を生成するためにそれらのカップルを使用してい

SELECT 
     StateId, 
     COUNT(*) AS TotalCount, 
     SUM(CASE WHEN PropertyTypeId = 1 THEN 1 ELSE 0 END) as SFRCount, 
     SUM(CASE WHEN PropertyTypeId <> 1 THEN 1 ELSE 0 END) as OtherCount 
    FROM Property AS P 
    GROUP BY StateId 
    HAVING (COUNT(*) > 99) 
    ORDER BY StateId 
+3

私の経験では、「SUM(CASE ...)」はインナーセレクトと比較して驚くほど速い傾向があります。 – ean5533

+2

恐ろしい、ありがとう!私はあなたの答えを編集して、 "OtherCount"の後に無関係なコンマを削除しました。 – Scott

+0

+1、素晴らしい答え –

0

あなた代わりに、WHERE条件を結合パラメータとして使用するPropertyの1回の自己結合があります。 OtherCountは、派生クエリ内のTotalCount - SFRCountを減算することによって導き出すことができます。

0

別の方法としては、次のようにピボット機能を使用することです:

SELECT StateID, [1] + [2] AS TotalCount, [1] AS SFRCount, [2] AS OtherCount 
FROM Property 
PIVOT (COUNT(PropertyTypeID) 
     FOR PropertyTypeID IN ([1],[2]) 
     ) AS pvt 
WHERE [1] + [2] > 99 

あなたは困難なことができ、各プロパティのタイプのエントリを追加する必要がありますが、それは別の代替です。スコットは素晴らしい答えを持っています。

0

PropertyTypeIdがnullでない場合は、単一の結合でこれを行うことができます。 CountはSumより高速です。しかし、Count + JoinはSumより速く結合します。以下のテストケースは、あなたのデータを模倣しています。 docSVsysには800,000行があり、caseIDには約300の一意の値があります。このテストケースのカウントプラス結合は、合計よりわずかに速いです。しかし、私がwith(nolock)を取り除くと、合計は約1/4速くなります。あなたのデータでテストする必要があります。

select GETDATE() 
    go; 
    select caseID, COUNT(*) as Ttl, 
     SUM(CASE WHEN mimeType = 'message/rfc822' THEN 1 ELSE 0 END) as SFRCount, 
     SUM(CASE WHEN mimeType <> 'message/rfc822' THEN 1 ELSE 0 END) as OtherCount, 
     COUNT(*) - SUM(CASE WHEN mimeType = 'message/rfc822' THEN 1 ELSE 0 END) as OtherCount2 
    from docSVsys with (nolock) 
    group by caseID 
    having COUNT(*) > 1000 
    select GETDATE() 
    go; 
    select docSVsys.caseID, COUNT(*) as Ttl 
    , COUNT(primaryCount.sID) as priCount 
    , COUNT(*) - COUNT(primaryCount.sID) as otherCount 
    from docSVsys with (nolock) 
    left outer join docSVsys as primaryCount with (nolock) 
     on primaryCount.sID = docSVsys.sID 
     and primaryCount.mimeType = 'message/rfc822' 
    group by docSVsys.caseID 
    having COUNT(*) > 1000 
    select GETDATE() 
    go;