È possibile specificare la condizione in Count ()?


392

È possibile specificare una condizione in Count()? Vorrei contare solo le righe che hanno, ad esempio, "Manager" nella colonna Posizione.

Voglio farlo nell'istruzione count, non usando WHERE; Mi sto chiedendo su di esso perché ho bisogno di contare sia gestori e gli Altri nella stessa SELECT(qualcosa di simile Count(Position = Manager), Count(Position = Other))quindi WHEREè inutile per me in questo esempio.


4
Ciao a tutti gli * utenti, usa Count (SomeColumnInYourTable) dove Position = 'Manager'
Mark Dickinson,

6
@Mark: su tutti i database moderni, questo non fa alcuna differenza.
Philippe Leybaert,

5
@Mark & ​​Philippe: In realtà può fare la differenza. Se il campo è nullable e non indicizzato, la query deve toccare ogni record nella tabella, quindi l'uso di count (*) e count (field) può dare risultati differnet e prestazioni diverse.
Guffa,

4
Ho analizzato i piani di esecuzione per count (*) vs count (x) per anni, e finora non ne ho trovato uno che abbia mostrato differenze nelle prestazioni. Ecco perché mi piacerebbe davvero vedere un esempio di una query in cui c'è una differenza.
Philippe Leybaert,

3
@Matthew: non stiamo parlando SELECT *, ma SELECT COUNT(*), che è una bestia totalmente diversa.
Philippe Leybaert,

Risposte:


664

Se non puoi semplicemente limitare la query stessa con una whereclausola, puoi utilizzare il fatto che l' countaggregato conta solo i valori non nulli:

select count(case Position when 'Manager' then 1 else null end)
from ...

Puoi anche usare l' sumaggregato in modo simile:

select sum(case Position when 'Manager' then 1 else 0 end)
from ...

cosa succede se il mio campo è intero e voglio abbinare null. non funziona in questo modo selezionare count (case IntegerField quando 'NULL' quindi 1 altro null end) da
Faizan

2
@Faizan nullè speciale. Usacase when IntegerField is null then ...
Peet Brits il

Quando si lavora con campi booleani è possibile utilizzare questo:SUM(CONVERT(int, IsManager))
Simon_Weaver

2
SQL Server implica istruzioni else nullfor case, quindi l' count()esempio può essere più corto di 10 caratteri (se si conta lo spazio).
Michael - Dov'è Clay Shirky il

213

Supponendo che non si desideri limitare le righe restituite perché si stanno aggregando anche altri valori, è possibile farlo in questo modo:

select count(case when Position = 'Manager' then 1 else null end) as ManagerCount
from ...

Diciamo che nella stessa colonna c'erano i valori di Manager, Supervisor e Team Lead, potevi ottenere i conteggi di ciascuno in questo modo:

select count(case when Position = 'Manager' then 1 else null end) as ManagerCount,
    count(case when Position = 'Supervisor' then 1 else null end) as SupervisorCount,
    count(case when Position = 'Team Lead' then 1 else null end) as TeamLeadCount,
from ...

3
@RedFilter Non è nemmeno necessario specificare la elseparte, appena enddopo 1.
Denis Valeev,

7
@Denis: corretto - spesso lascio elsedentro perché documenta meglio i risultati dell'istruzione case, specialmente per gli sviluppatori novie SQL. Per brevità, può essere rimosso in questo caso.
RedFilter,

30

La risposta di @Guffa è eccellente, basta sottolineare che forse è più pulito con un'istruzione IF

select count(IF(Position = 'Manager', 1, NULL)) as ManagerCount
from ...

21

Dipende da cosa intendi, ma l'altra interpretazione del significato è dove vuoi contare le righe con un certo valore, ma non vuoi limitare SELECTJUST a quelle righe ...

Lo faresti usando SUM()una clausola in, in questo modo invece di usare COUNT(): es

SELECT SUM(CASE WHEN Position = 'Manager' THEN 1 ELSE 0 END) AS ManagerCount,
    SUM(CASE WHEN Position = 'CEO' THEN 1 ELSE 0 END) AS CEOCount
FROM SomeTable

13

È inoltre possibile utilizzare la parola chiave pivot se si utilizza SQL 2005 o versioni successive

maggiori informazioni e da Technet

SELECT *
FROM @Users
PIVOT (
    COUNT(Position)
    FOR Position
    IN (Manager, CEO, Employee)
) as p

Test Data Set

DECLARE @Users TABLE (Position VARCHAR(10))
INSERT INTO @Users (Position) VALUES('Manager')
INSERT INTO @Users (Position) VALUES('Manager')
INSERT INTO @Users (Position) VALUES('Manager')
INSERT INTO @Users (Position) VALUES('CEO')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')

5

Intendi solo questo:

SELECT Count(*) FROM YourTable WHERE Position = 'Manager'

Se è così, allora sì che funziona!


1
La modifica mostra che non vuole limitare le righe con una clausola WHERE
KinSlayerUY

4

So che questo è davvero vecchio, ma mi piace il NULLIFtrucco per tali scenari e finora non ho trovato aspetti negativi. Guarda la mia copia e il mio esempio incollabile, che non è molto pratico, ma mostra come usarlo.

NULLIF potrebbe darti un piccolo impatto negativo sulle prestazioni, ma suppongo che dovrebbe essere ancora più veloce delle sottoquery.

DECLARE @tbl TABLE ( id [int] NOT NULL, field [varchar](50) NOT NULL)

INSERT INTO @tbl (id, field)
SELECT 1, 'Manager'
UNION SELECT 2, 'Manager'
UNION SELECT 3, 'Customer'
UNION SELECT 4, 'Boss'
UNION SELECT 5, 'Intern'
UNION SELECT 6, 'Customer'
UNION SELECT 7, 'Customer'
UNION SELECT 8, 'Wife'
UNION SELECT 9, 'Son'

SELECT * FROM @tbl

SELECT 
    COUNT(1) AS [total]
    ,COUNT(1) - COUNT(NULLIF([field], 'Manager')) AS [Managers]
    ,COUNT(NULLIF([field], 'Manager')) AS [NotManagers]
    ,(COUNT(1) - COUNT(NULLIF([field], 'Wife'))) + (COUNT(1) - COUNT(NULLIF([field], 'Son'))) AS [Family]
FROM @tbl

Commenti apprezzati :-)


2
SELECT COUNT(*) FROM bla WHERE Position = 'Manager'

2

Penso che puoi usare una semplice clausola WHERE per selezionare solo il conteggio di un record.


Perché ottengo un voto negativo? Dopo che ho risposto (o potrebbe essere la stessa volta), molte persone hanno risposto alla stessa cosa e non ottengono alcun voto negativo. / :(
NawaMan,

4
Si ottiene un downvote perché la domanda è "specificare la condizione nel conteggio" NON "Contare i valori per condizione". Quindi stai rispondendo alla domanda sbagliata
Radon8472

3
È un po 'ingiusto sottovalutare la risposta, quando la risposta è stata scritta era una soluzione corretta alla domanda .... ha aggiunto il testo aggiuntivo 4 minuti dopo questa risposta!
Peter,

2

Ecco cosa ho fatto per ottenere un set di dati che includesse sia il totale che il numero che soddisfacevano i criteri, all'interno di ciascun container di spedizione. Ciò mi consente di rispondere alla domanda "Quanti container hanno più dell'X% degli articoli oltre la taglia 51"

select
   Schedule,
   PackageNum,
   COUNT (UniqueID) as Total,
   SUM (
   case
      when
         Size > 51 
      then
         1 
      else
         0 
   end
) as NumOverSize 
from
   Inventory 
where
   customer like '%PEPSI%' 
group by
   Schedule, PackageNum


-4

Usando questo otterrai il conteggio per i manager

Select Position, count(*) as 'Position Counter'
from your_table 
group by Position 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.