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.

¿Quién puede negar que todos los días se aprende algo nuevo?

Día a día, nuestro cerebro se sigue llenando de conocimiento, pero muchas veces esas cosas que aprendemos las vamos acumulando como papeles en un escritorio, que algún día organizaremos y leeremos detenidamente.

Cuando estamos estudiando, o en el trabajo, y estamos realizando un proyecto, muchas veces pasamos buscando y rebuscando la solución para algún problema particular, y muchas veces ese problema ya le sucedió al compañero que esta a lado, o a un amigo de la U, pero ninguno de ellos, hizo nada por transmitir ese conocimiento. Y para evitar que eso siga ocurriendo es que hemos dado vida a tips de web.

Ya que el mundo web es tan inmenso y tan variado, cada persona que se adentra en el, va aprendiendo cosas muy particulares de acuerdo a sus intereses: diseño, programación, posicionamiento en buscadores, publicidad, bases de datos, etc. Y esto mismo, nos ocurre a nosotros, un grupo de web developers, SEOs, DBAs, casi ingenieros en sistemas y en general usuarios de la web, que todos los días, ya sea en el trabajo, en los blogs, a la hora del almuerzo, en los free lances, o donde sea, vamos acumulando una buena cantidad de tips que nos salvan la vida.

Aunque no seamos expertos conocedores, o tengamos grandes habilidades para publicar artículos, nos concentraremos en plasmar nuestro tip, de forma simple y sencilla, esperando que esas cosas que vamos aprendiendo, les sirvan a alguien, y que podamos aportar algo, y mejor aún, que podamos retroalimentarnos con los comentarios y sugerencias, para lograr mejorar todos juntos y hacer que la comunidad de desarrolladores Web siga creciendo en Guatemala, Latino América y el mundo.

Hasta muy pronto! y esperemos que día a día, siempre hayan tips de a web!!