COUNTIF toplama işlevinin SQL Server eşdeğeri


164

GROUP BYSadece belirli bir koşula (örneğin yalnızca belirli bir sütun değeri 1'e eşit olduğu kayıtları saymak) dayalı kayıt sayma yeteneği gerektiren bir cümle ile bir sorgu inşa ediyorum .

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()Orada denilen hiçbir yerli SQL fonksiyonu olduğu için çizgi Açıkçası başarısız COUNTIF, ama buradaki fikir Sütunum değerini '1' olan tüm satırları yüzdesini belirlemektir.

MS SQL 2005 ortamında düzgün bir şekilde nasıl uygulanacağı hakkında herhangi bir düşünce?

Yanıtlar:


339

Aşağıdaki gibi bir ifadeyle birleştirilmiş SUM(değil COUNT!) Kullanabilirsiniz CASE:

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

Not: Kendi testlerimde NULLbir sorun değildi, ancak bu çevreye bağlı olabilir. Null'ları şu şekilde işleyebilirsiniz:

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

3
(OP'nin MS SQL hakkında sorduğunu biliyorum, ancak aynı şeyi yapan SQLite kullanıcıları için sadece küçük bir yorum var) SQLite ISNULL, bunun yerine yapabilir CASE WHEN myColumn IS NULLveya kullanabilirsiniz ifnull( stackoverflow.com/a/799406/1861346 )
Matt

54

Genellikle Josh'un önerisini yapıyorum, ama paylaşmak istediğim biraz hokey alternatifini beyin fırtınası yaparak test ettim.

COUNT (ColumnName) öğesinin NULL saymaması gerçeğinden faydalanabilir ve şöyle bir şey kullanabilirsiniz:

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

NULLIF - Girilen iki değer aynı ise NULL döndürür.

Avantajı: SUM () gösterimi yerine COUNT satıra yönelik niyetinizi ifade eder. Dezavantajı: Nasıl çalıştığı net değil ("büyü" genellikle kötüdür).


2
Bu çözüm, bir grup yalnızca 0 yerine null değeri verdiğinde toplamdan farklı bir yanıt verebilir.
KimvdLinde

Eski yazı, ama teşekkürler bu yardımcı oldu. Büyü genişletilmiş ve ekleyerek "yalnızca Boşlara" sorunu etrafında var ISNULLşöyle: SELECT COUNT(NULLIF(0, ISNULL(myColumn, 0))). Bekle, bu sadece çirkin görünüyor ...
pcdev

1
NULLIFNOT işlevi olsaydı mükemmel olurdu
qwertzguy

21

Bu sözdizimini kullanırdım. Josh ve Chris'in önerileri ile aynıdır, ancak avantajı ile ANSI uyumludur ve belirli bir veritabanı satıcısına bağlı değildir.

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

2
Chris'in cevabı Stndard SQL uyumludur (ipucu: NULLIFStandart SQL-92 dahildir). Josh'un cevabı kolayca değiştirerek Standart SQL dönüştürülebilir isnullile COALESCE.
oneday31

Aslında bu cevabı en çok sevdim, çünkü Chris'in gösterdiği "satırları sayma" fikrini alır, ancak herhangi bir karşılaştırma operatörü kullanabileceğiniz için daha genişletilebilir; sadece değil =. "Yanıt sayısı> = 2" için kullanıyorum.
Kristen Hammack

3

Josh'un cevabına ek olarak,

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

'Sayıyı' bir 'toplam' olarak değiştirmeden benim için (SQL Server 2012'de) iyi çalıştı ve aynı mantık diğer 'koşullu toplamalara' taşınabilir. Örneğin, bir koşula göre toplama:

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

2

Peki ya

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

Şundan kısa CASE:)

İşleri nedeniyle COUNT()boş değerler saymak ve yok IF/ CASEdönüş null adlı koşul karşılanmadığında ve hiçbir yoktur ELSE.

Bence kullanmaktan daha iyi SUM().


1

Ürüne özgü değil, ancak SQL standardı

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

bu amaç için. Ya da ona çok benzeyen bir şey, şapkamın üstünden bilmiyorum.

Ve tabii ki satıcılar kendi özel çözümlerine bağlı kalmayı tercih edecekler.


1
Bunu daha önce hiç duymamıştım, bu yüzden baktım. Modern-sql.com/feature/filter 'e göre fıkrayı gerçekten sunan tek büyük DBMS FILTERPostgreSQL'dir, ancak hepsinde öykünürCASE .
Kristen Hammack

1

Neden böyle olmasın?

SELECT count(1)
FROM AD_CurrentView
WHERE myColumn=1

1
Çünkü sayımdan çok daha fazlasına ihtiyacı var. Bir grubun bir bölümünün satır sayımını ve ardından bir grubun bir kümesini, bir YER ile yapamayacağınızı almaya çalışıyor.
Kristen Hammack

1

Benim durumumda SELECT sütunlarımın bir parçası olarak COUNTIF () kullanmak zorunda kaldım VE her öğenin sonuçlarımda kaç kez göründüğünü taklit etmek zorunda kaldım.

Bu yüzden kullandım ...

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

Tabii ki sonucu görüntüleme gereksinimlerinize göre biçimlendirmeniz gerekecektir.


-2
SELECT COALESCE(IF(myColumn = 1,COUNT(DISTINCT NumberColumn),NULL),0) column1,
COALESCE(CASE WHEN myColumn = 1 THEN COUNT(DISTINCT NumberColumn) ELSE NULL END,0) AS column2
FROM AD_CurrentView
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.