SQL Server-equivalent van een COWIF-aggregaatfunctie

Ik bouw een query met een GROUP BYclausule die de mogelijkheid heeft om records te tellen op basis van een bepaalde conditie (bijvoorbeeld alleen records waar een bepaalde kolomwaarde gelijk is aan 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

De COUNTIF()LINE FUNLENTELIJK MINDIGEN Sinds er geen native SQL-functie is genaamd COUNTIF, maar het idee hier is om het percentage van alle rijen te bepalen die de waarde hebben ‘1’ voor mycolumn.

eventuele gedachten over hoe dit goed kan implementeren in een MS SQL 2005-omgeving?


Antwoord 1, Autoriteit 100%

U kunt een SUM(niet COUNT!) Gecombineerd met een CASEverklaring, zoals deze:

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

Opmerking: in mijn eigen test NULLs waren geen probleem, hoewel dit kan zijn, afhankelijk van de omgeving. Je zou nulls kunnen verwerken, zoals:

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

Antwoord 2, Autoriteit 16%

Ik doe meestal wat Josh aanbevolen, maar brainstormde en testte een enigszins Hokey-alternatief dat ik voelde als het delen.

U kunt profiteren van het feit dat telling (kolomnaam) geen nulls telt, en iets als deze gebruiken:

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

NULLIF – geeft NULL terug als de twee doorgegeven waarden hetzelfde zijn.

Voordeel: drukt uw intentie uit om rijen COUNT te gebruiken in plaats van de SUM()-notatie.
Nadeel: niet zo duidelijk hoe het werkt (“magie” is meestal slecht).


Antwoord 3, autoriteit 7%

Ik zou deze syntaxis gebruiken. Het bereikt hetzelfde als de suggesties van Josh en Chris, maar met het voordeel dat het ANSI-compatibel is en niet gebonden is aan een bepaalde databaseleverancier.

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

Antwoord 4

Wat dacht je van

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

Korter dan CASE🙂

Werkt omdat COUNT()geen null-waarden telt, en IF/CASEgeeft null terug als niet aan de voorwaarde wordt voldaan en er is nee ELSE.

Ik denk dat het beter is dan SUM()te gebruiken.


Antwoord 5

Aanvullend op Josh’s antwoord,

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

Werkte goed voor mij (in SQL Server 2012) zonder de ‘count’ te veranderen in een ‘sum’ en dezelfde logica is overdraagbaar naar andere ‘conditionele aggregaten’. Bijvoorbeeld optellen op basis van een voorwaarde:

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

Antwoord 6

Waarom vind je dit niet leuk?

SELECT count(1)
FROM AD_CurrentView
WHERE myColumn=1

Antwoord 7

In mijn geval moest ik AANTAL.ALS() gebruiken als onderdeel van mijn SELECT-kolommen EN om een % na te bootsen van het aantal keren dat elk item in mijn resultaten verscheen.

Dus ik gebruikte dit…

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

Natuurlijk moet u het resultaat opmaken volgens uw weergavevereisten.


Antwoord 8

Niet productspecifiek, maar de SQL-standaard biedt

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

voor dit doel. Of iets dat er sterk op lijkt, weet ik niet uit mijn hoofd.

En natuurlijk houden leveranciers liever vast aan hun eigen oplossingen.


Antwoord 9

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

Other episodes