0

私は次の声明を持っています:

SELECT
    (CONVERT(VARCHAR(10), f1, 120)) AS ff1,
    CONVERT(VARCHAR(10), f2, 103) AS ff2,
    ...,
    Bonus,
    Malus,
    ClientID,
FROM 
    my_table                        
WHERE
    <my_conditions>
ORDER BY 
    f1 ASC

この選択では、ClientID ごとに複数の行が返されます。空でないボーナスまたはマルスの行を持たないクライアントのすべての行を除外する必要があります。

この select を1 つのステートメントだけで変更し、この select をすべて複製することなく、どうすればそれを行うことができますか?

結果を #temp_table に保存してから、データをグループ化し、グループ化の結果を使用して一時テーブルをフィルター処理できます。-しかし、私はそれを1つのステートメントだけで行う必要があります

この選択を 2 回実行できます。1 回はグループ化してから、グループ化の結果に基づいて行をフィルタリングできます。しかし、私はそれを 2 回選択したくありません

CTE (Common Table Expressions) は、ここで選択を 1 回だけ実行し、結果をグループ化に使用してから、グループ化の結果に基づいて目的の結果を選択できるようにするのに役立つ可能性があります。

この問題に対するよりエレガントな解決策はありますか?

前もって感謝します!

SQL が何をすべきかを明確にするために、例を追加します。

ClientID  Bonus  Malus
1         1      
1                
1                1
2                
2                
3         4      
3                5
3         1      

したがって、この場合、ClientID=2 行を表示したくありません (それらは興味深いものではありません)。結果は次のようになります。

ClientID  Bonus  Malus
1         1      
1                
1                1
3         4      
3                5
3         1      
4

3 に答える 3

0
SELECT Bonus,
       Malus,
       ClientID
FROM my_table                        
WHERE ClientID not in 
(
  select ClientID
  from my_table
  group by ClientID
  having count(Bonus) = 0 and count(Malus) = 0
)
于 2013-07-14T12:00:11.833 に答える
0

CTE は問題なく動作しますが、CTE が使用されているすべての場所にコンテンツが複製されるため、実際にはそのコンテンツは 2 回実行されます。これは、一時テーブルを使用する場合と比較して、正味のパフォーマンスの勝敗を左右する可能性があります。クエリが非常に高価な場合、損失として出てくる可能性があります。安価な場合、または多くの行が返される場合、一時テーブルは比較に失敗します。

どちらのソリューションが優れていますか? 実行計画を見て、パフォーマンスを測定します。

CTE は、より簡単で保守しやすく、冗長性の少ない代替手段です。

于 2013-07-14T12:08:52.873 に答える