2009-02-24 7 views
123

特定の条件(たとえば、特定の列の値が1のレコードのみ)に基づいてレコードをカウントする機能を必要とするGROUP BY句でクエリを作成しています。Sql ServerのCOUNTIF集合関数と同等

SELECT UID, 
     COUNT(UID) AS TotalRecords, 
     SUM(ContractDollars) AS ContractDollars, 
     (COUNTIF(MyColumn, 1)/COUNT(UID) * 100) -- Get the average of all records that are 1 
FROM dbo.AD_CurrentView 
GROUP BY UID 
HAVING SUM(ContractDollars) >= 500000 

COUNTIFと呼ばれるネイティブSQL関数が存在しないのでCOUNTIF()ラインは明らかに失敗しますが、ここでの考え方は、MYCOLUMNの値「1」を持つすべての行の割合を決定することです。

MS SQL 2005環境でこれを正しく実装する方法について考えていますか?

SELECT SUM(CASE WHEN myColumn=1 THEN 1 ELSE 0 END) 
FROM AD_CurrentView 

注:

答えて

241

あなたはSUM(!ないCOUNTCASE声明と合わせ、このように使用することができNULL sが問題ではありませんでした私自身のテストでは、これは環境に依存することができても。次のようなヌル扱うことができる:

SELECT SUM(CASE WHEN ISNULL(myColumn,0)=1 THEN 1 ELSE 0 END) 
FROM AD_CurrentView 
+0

(私はMSのSQLについて質問しましたが、同じことをやっているSQLiteユーザのためのちょっとしたコメントがあります)SQLiteには 'ISNULL'がありません。代わりに' CASE WHEN myColumn IS NULL'を使うか、 'ifnull' (https://stackoverflow.com/a/799406/1861346) – Matt

43

を私は通常ジョシュが推奨何が、私は共有のように感じた少し陳腐な代替案を出し合い、テスト。

あなたはCOUNT(ColumnNameには)NULLをカウントし、このような何かを使用しないという事実を利用することができます。

SELECT COUNT(NULLIF(0, myColumn)) 
FROM AD_CurrentView 

NULLIF - の値に渡された2つが同じである場合はNULLを返します。

利点:SUM()表記ではなく、COUNT行にインテントを表現します。 短所:どのように動作しているかはっきりしていません(通常は「魔法」は悪いです)。

+2

この解決策は、グループにヌルのみが含まれている場合、合計値とは異なる答えを与えることができます。 – KimvdLinde

+0

古い投稿ですが、これは助けになりました。私はこの魔法を拡張し、次のように 'ISNULL'を追加することによって"唯一のNULL "問題を回避しました:' SELECT COUNT(NULLIF(0、ISNULL(myColumn、0))) '。待って、ちょうど醜く見える... – pcdev

16

この構文を使用します。これはJoshとChrisの提案と同じですが、利点はANSIであり、特定のデータベースベンダーに縛られていない点です。

select count(case when myColumn = 1 then 1 else null end) 
from AD_CurrentView 
+2

クリスの答えはスタンダードSQLに準拠しています(ヒント: 'NULLIF'は標準SQL-92に含まれています)。 Joshの答えは 'isnull'を' COALESCE'に置き換えることでStandard SQLに簡単に変換できます。 – onedaywhen

+0

私はChrisが表示していた "行を数える"というアイデアを得ているので、実際にこの答えが一番好きですが、比較演算子を使用できるので、より拡張性があります。 '='だけではありません。私はそれを使用している "応答の数をカウント> = 2"。 –

0

ない製品固有のが、SQL標準では、この目的のために

SELECT COUNT() FILTER WHERE <condition-1>, COUNT() FILTER WHERE <condition-2>, ... FROM ...

を提供します。それとよく似ているもの、私は帽子の上から知りません。

もちろん、ベンダーは独自のソリューションを採用したいと考えています。

+1

私は以前これについて聞いたことがなかったので、私はそれを探しました。 http://modern-sql.com/feature/filterによれば、実際に 'FILTER'節を提供する唯一の主要なDBMSはPostgreSQLですが、それらのすべてで' CASE'によってエミュレートされています。 –

0

なぜこれが気に入りませんか?

ジョシュの答えへに追加
SELECT count(1) 
FROM AD_CurrentView 
WHERE myColumn=1 
+0

彼はちょうどカウントより多くを必要とするので。彼はグループの一部の行数を取得しようとしていますし、グループ全体の集計をしていますが、それはWHEREではできません。 –

1

SELECT COUNT(CASE WHEN myColumn=1 THEN AD_CurrentView.PrimaryKeyColumn ELSE NULL END) 
FROM AD_CurrentView 

は「合計」と同じロジックに「数」を変更せずに(SQL Server 2012の中で)私のためによく働い他に移植可能です "条件付き集約 '例えば。およそ

SELECT id, COUNT(IF status=42 THEN 1 ENDIF) AS cnt 
FROM table 
GROUP BY table 

短いCASE :)

作品よりもCOUNT()ので、null値をカウントしない方法

SELECT SUM(CASE WHEN myColumn=1 THEN AD_CurrentView.NumberColumn ELSE 0 END) 
FROM AD_CurrentView 
0

、およびIF/CASEリターンヌル条件:条件に基づく加算が満たされておらず、ELSEがありません。

SUM()よりも優れていると思います。

0

私の場合、SELECTカラムの一部としてCOUNTIF()を使用し、各項目が自分の検索結果に表示された回数の%を模倣する必要がありました。

だから私はお使いのディスプレイの要件に応じて結果をフォーマットする必要があります...もちろん

SELECT COL1, COL2, ... ETC 
     (1/SELECT a.vcount 
      FROM (SELECT vm2.visit_id, count(*) AS vcount 
        FROM dbo.visitmanifests AS vm2 
        WHERE vm2.inactive = 0 AND vm2.visit_id = vm.Visit_ID 
        GROUP BY vm2.visit_id) AS a)) AS [No of Visits], 
     COL xyz 
FROM etc etc 

これを使用していました。