¿Es posible especificar la condición en Count ()?


392

¿Es posible especificar una condición en Count() ? Me gustaría contar solo las filas que tienen, por ejemplo, "Administrador" en la columna Posición.

Quiero hacerlo en la declaración de conteo, no usando WHERE; Lo pregunto porque necesito contar tanto a los gerentes como a los demás en el mismo SELECT(algo Count(Position = Manager), Count(Position = Other))así WHEREno me sirve en este ejemplo.


44
Abuchear a todos los usuarios *, use Count (SomeColumnInYourTable) donde Position = 'Manager'
Mark Dickinson el

66
@ Mark: en todas las bases de datos modernas, esto no hace ninguna diferencia.
Philippe Leybaert

55
@ Mark y Philippe: En realidad, puede hacer una gran diferencia. Si el campo es anulable y no está indexado, la consulta debe tocar todos los registros de la tabla, por lo que el uso de count (*) y count (field) puede proporcionar resultados de red diferentes y un rendimiento diferente.
Guffa

44
He analizado los planes de ejecución para count (*) vs count (x) durante años, y hasta ahora no he encontrado ninguno que muestre una diferencia en el rendimiento. Es por eso que realmente me gustaría ver un ejemplo de una consulta donde hay una diferencia.
Philippe Leybaert

3
@Matthew: no estamos hablando SELECT *, pero SELECT COUNT(*), que es una bestia totalmente diferente.
Philippe Leybaert

Respuestas:


664

Si no puede limitar la consulta en sí con una wherecláusula, puede utilizar el hecho de que el countagregado solo cuenta los valores no nulos:

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

También puede usar el sumagregado de una manera similar:

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

¿Qué pasa si mi campo es entero y quiero coincidir con nulo? no funciona de esta manera, seleccione el recuento (caso IntegerField cuando 'NULL' y luego 1 final nulo) de
Faizan

2
@Faizan nulles especial. Usocase when IntegerField is null then ...
Peet Brits

Al trabajar con campos booleanos puede usar esto:SUM(CONVERT(int, IsManager))
Simon_Weaver

2
SQL Server implica una declaración else nullfor case, por lo que el count()ejemplo puede ser 10 caracteres más corto (si cuenta el espacio).
Michael - ¿Dónde está Clay Shirky?

213

Suponiendo que no desea restringir las filas que se devuelven porque también está agregando otros valores, puede hacerlo así:

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

Digamos que dentro de la misma columna que tenía valores de Gerente, Supervisor y Líder de equipo, podría obtener los recuentos de cada uno de esta manera:

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 Ni siquiera es necesario especificar la elseparte, solo enddespués de la 1.
Denis Valeev

77
@Denis: correcto: a menudo dejo la entrada elseya que documenta mejor los resultados de la declaración del caso, especialmente para los desarrolladores de SQL novatos. Por brevedad, se puede eliminar en este caso.
RedFilter

30

La respuesta de @Guffa es excelente, solo señale que tal vez sea más limpio con una declaración IF

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

21

Depende de lo que quiera decir, pero la otra interpretación del significado es donde desea contar las filas con un cierto valor, pero no desea restringirlas SELECTa SOLO esas filas ...

Lo harías usando SUM()una cláusula, como esta en lugar de usar COUNT(): ej.

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

También puede usar la palabra clave dinámica si está utilizando SQL 2005 o superior

Más información y de Technet

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

Conjunto de datos de prueba

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

¿Te refieres a esto?

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

Si es así, ¡sí, eso funciona!


1
La edición muestra que no quiere restringir las filas con una cláusula WHERE
KinSlayerUY

4

Sé que esto es muy antiguo, pero me gusta el NULLIFtruco para tales escenarios, y hasta ahora no encontré inconvenientes. Solo vea mi ejemplo de copiar y pegar, que no es muy práctico, pero demuestra cómo usarlo.

NULLIF podría darle un pequeño impacto negativo en el rendimiento, pero supongo que aún debería ser más rápido que las subconsultas.

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

Comentarios apreciados :-)


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

2

Creo que puede usar una simple cláusula WHERE para seleccionar solo el recuento de algunos registros.


¿Por qué recibo un voto negativo? Después de que respondí (o puede ser al mismo tiempo), muchas personas respondieron algo similar y no reciben ningún voto negativo. / :(
NawaMan

44
Recibes un voto negativo porque la pregunta es "especificar condición en Conteo" NO "Contar valores por condición". Entonces estás respondiendo la pregunta equivocada
Radon8472

3
Es un poco injusto rechazar la respuesta, cuando la respuesta fue escrita fue una solución correcta a la pregunta ... ¡agregó el texto extra 4 minutos después de esta respuesta!
Peter

2

Esto es lo que hice para obtener un conjunto de datos que incluía tanto el total como el número que cumplía los criterios, dentro de cada contenedor de envío. Eso me permite responder la pregunta "¿Cuántos contenedores de envío tienen más del X% de artículos de más del tamaño 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

Con esto obtendrás el recuento de gerentes

Select Position, count(*) as 'Position Counter'
from your_table 
group by Position 
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.