30
Hace ya más de una año que empecé a trabajar en desarrollo web. Unos de los sitios que trabajé fue un sistema para enviar tarjetas postales y recuerdo el dÃa en que me tocó ver como le hacÃa para hacer que un query que hacÃa varios counts sobre una misma tabla pasara de tardarse entre 3 minutos y 5 minutos a menos de un minuto (que es lo más que querÃa esperar mi jefe).
Era una tabla de regular tamaño, no con millones pero si con cientos de miles de tuplas, y recorrerla varias veces era un martirio, pues eso hacÃa que tardara tanto el query.
Probablemente hayan varias maneras de hacerlo, pero yo les presentaré 2 que fueron las me dieron resultado.
Solo antes de empezar, les comento que yo utilizo PostreSQL, la razón se las explicaré algún otro momento, asi que tomenlo muy en cuenta, si es que no encuentran las funciones que mencione en algunos de mis tips.
Vamos a imaginar que la tabla tiene la siguiente estructura y los siguientes datos (Adjunto los scripts):
|
id
|
color
|
forma
|
estado
|
marca
|
| 1 | rojo | cuadrado | inactivo | nike |
| 2 | azul | redondo | dormido | adidas |
| 3 | cafe | cuadrado | activo | mcdonalds |
| 4 | negro | triangular | dormido | nike |
| 5 | rojo | redondo | activo | dell |
| 6 | azul | redondo | activo | adidas |
| 7 | blanco | cubica | inactivo | nintendo |
| 8 | morado | triangular | activo | microsoft |
| 9 | verde | cuadrado | dormido | dell |
| 10 | negro | rectangular | activo | mac |
Por ejemplo, si queremos contar cuantos hay en cada estado podemos ejecutar:
SELECT estado,COUNT(estado)
FROM multiplecount
GROUP BY estado
Lo cual nos da:
|
Estado
|
Count()
|
|
activo
|
5
|
|
dormido
|
3
|
|
inactivo
|
2
|
Aja!!, pero si queremos contar cuantos activos, cuantos dormidos, cuantos redondos y cuantos nike hay, allà ya se complica y usamos
- El tip del CASE
SELECT
COUNT(CASE estado WHEN 'activo' THEN 1 ELSE null END) AS activos,
COUNT(CASE estado WHEN 'dormido' THEN 1 ELSE null END) AS dormidos,
COUNT(CASE forma WHEN 'redondo' THEN 1 ELSE null END) AS redondos,
COUNT(CASE marca WHEN 'nike' THEN 1 ELSE null END) AS nike
FROM multiplecount
Lo cual nos da:
|
activos
|
dormidos
|
redondos
|
nike
|
|
5
|
3
|
3
|
2
|
Este query hace uso de la premisa que la función COUNT() únicamente cuenta valores no nulos, por lo que cuando algo no cumple la condición le asignamos NULL y no lo cuenta, y si cumple la condición entonces le asignamos un valor, en este caso 1, para que lo cuente.
La otra forma de hacerlo es usando
- El tip del NULLIF
SELECT
COUNT(NULLIF(estado='activo',false)) AS activos,
COUNT(NULLIF(estado='dormido',false)) AS dormidos,
COUNT(NULLIF(forma='redondo',false)) AS redondos,
COUNT(NULLIF(marca='nike',false)) AS nike
FROM multiplecount
Esto ya se complica un poco más, si es que no han usado la función NULLIF, o su equivalente en el dbms de su elección.
NULLIF devuelve null si los parametro son iguales, y devuelve el primer parametro si son distintos. Veamoslo despacio y con dibujitos, como lo diriamos comunmente:
Si hacemos NULLIF('el mundo es redondo',falso) nos devolverÃa el primer parametro: ‘el mundo es redondo’ ya que eso es verdadero y el segundo parametro es falso.
Si hacemos NULLIF('el mundo es cuadrado',falso) nos devolverÃa NULL, ya que ‘el mundo es cuadrado’ es falso y el segundo parametro es falso, por ser iguales retornarÃa NULL.
Lo mismo ocurre con NULLIF(estado='activo',false)) en las tuplas en que estado sea ‘activo’ el valor sera verdadero y como el segundo parametro es false entonces retorna true (que es el valor de evaluar esatdo=’activo’ para las tuplas que cumplan con esa condición). Y cómo true es un valor no nulo COUNT() lo tomarÃa en cuenta, en cambio en los valores en que estado<>’activo’ retornara false y como el segundo parametro es false, y esos valores son iguales, entonces retornara NULL, por los que count() no los tomará en cuenta.
Estas son las dos formas en que yo hago multiples counts en un mismo query sobre una tabla, prácticamente son la misma cosa, pero unos dicen papas y otros patatas, jeje.
Espero que les sirva, y que algún dÃa los saque de apuros, jejeje.
Hasta la próxima.
Gracias a kementeus, pues el fue quien me enseño la forma usando el NULLIF.
Muy interesante y un excelente tip. Multiples count pense…? mmmmm.
Muchas gracias, adelante.