web-dev-qa-db-ja.com

COUNTIF集計関数に相当するSQL Server

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

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環境に適切に実装する方法についての考えはありますか?

147
senfo

次のように、SUMステートメントと組み合わせてCOUNTCASEではなく!)を使用できます。

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

注:私自身のテストではNULLsは問題ではありませんでしたが、これは環境に依存する可能性があります。次のようなヌルを処理できます。

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

私は通常、ジョシュが推奨したことを行いますが、共有したいと思ったちょっと変わった選択肢をブレインストーミングしてテストしました。

COUNT(ColumnName)はNULLをカウントしないという事実を利用して、次のようなものを使用できます。

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

NULLIF-渡された2つの値が同じ場合、NULLを返します。

利点:SUM()表記の代わりにCOUNT行に意図を表現します。欠点:どのように機能するかは明確ではありません(「魔法」は通常悪いです)。

46
Chris Shaffer

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

select count(case when myColumn = 1 then 1 else null end)
from   AD_CurrentView
18
asgeo1

ジョシュの答えに加えて、

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

「カウント」を「合計」に変更することなく(SQL Server 2012で)うまく機能し、同じロジックが他の「条件付き集計」に移植可能です。たとえば、条件に基づいた合計:

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

なぜこれが好きではないのですか?

SELECT count(1)
FROM AD_CurrentView
WHERE myColumn=1
0
Michal

どう?

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

CASEより短い:)

COUNT()はnull値をカウントせず、条件が満たされていないときにIF/CASEがnullを返し、ELSEがないため、動作します。

SUM()を使用するよりも良いと思います。

0
maf-soft

私の場合、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

もちろん、ディスプレイの要件に従って結果をフォーマットする必要があります。

0
Fandango68

製品固有ではありませんが、SQL標準は以下を提供します

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

この目的のために。またはそれによく似た何か、私は私の帽子の上から知らない。

そしてもちろん、ベンダーは独自のソリューションに固執することを好みます。

0
Erwin Smout