5th Dec 2022 Lectura de 4 minutos Patrones SQL útiles: Resumen condicional con CASE Aldo Zelen funciones de agregado CASE resumen condicional Patrones de SQL Índice ¿Qué es el resumen condicional? Espera, ¿cómo ha funcionado? Cuando comience a codificar en SQL, utilizará algunas sentencias y técnicas una y otra vez. Los llamamos "patrones SQL". Esta serie examinará los patrones SQL más comunes y considerará cómo utilizarlos. Anteriormente, vimos El patrón SQL de coincidencia de NULLs. Esto es importante cuando se comparan columnas que contienen valores NULL. Hoy, vamos a considerar otra práctica de SQL: la integración condicional con el operador CASE. ¿Qué es el resumen condicional? Cuando se utilizan funciones de agregación para crear consultas de informes, es frecuente que se utilice la integración condicional con el operador CASE. Recuerde que CASE devuelve un valor basado en criterios definidos. (Para obtener más información sobre la expresión CASE, consulte este artículo y este otro.) Cuando se realiza una integración con CASE, simplemente se están sumando (integrando) los valores que cumplen la expresión CASE. Obviamente, usarás la parte SUM de la consulta para agregar estos valores. Sé que parece complicado, pero no lo es. Utilicemos un ejemplo sencillo para explicarlo. Empezaremos por considerar una tabla básica transactions que contiene datos transaccionales de una pequeña empresa. La tabla transactions tabla tiene estas columnas: id - Un identificador único para cada transacción datetime - La marca de tiempo de la transacción customer - El ID del cliente creditcard - El ID del tipo de tarjeta de crédito utilizada amount - El importe de la transacción, en dólares account - El número de cuenta del cliente type - El tipo de transacción Estos son los datos que encontraríamos en una tabla como ésta: datetime customer creditcard amount account type 2017-01-01 00:00:00.000000 1 1 100 1 type_1 2017-03-01 00:00:00.000000 2 1 350 1 type_1 2017-05-01 00:00:00.000000 3 1 10 1 type_3 2017-02-01 00:00:00.000000 2 1 10 1 type_2 2017-05-01 00:00:00.000000 2 1 10 1 type_1 2017-04-01 00:00:00.000000 3 1 600 1 type_3 2017-01-01 00:00:00.000000 3 1 350 1 type_3 2017-03-01 00:00:00.000000 1 1 150 1 type_1 2017-04-01 00:00:00.000000 1 1 200 1 type_1 2017-02-01 00:00:00.000000 1 1 50 1 type_2 2017-05-01 00:00:00.000000 1 1 210 1 type_2 2017-04-01 00:00:00.000000 2 1 600 1 type_3 2017-01-01 00:00:00.000000 2 1 100 1 type_1 Queremos encontrar la suma de los importes de las transacciones y el número de transacciones realizadas antes del 1 de abril. Además, queremos que se listen por cliente individual. Podríamos conseguirlo con la siguiente consulta: SELECT customer, SUM( CASE WHEN datetime >= TIMESTAMP '2017-04-01' THEN amount ELSE 0 END ) AS sum_amount_after, SUM(CASE WHEN datetime >= TIMESTAMP '2017-04-01' THEN 1 ELSE 0 END) AS transaction_count_after, SUM(CASE WHEN datetime < TIMESTAMP '2017-04-01' THEN amount ELSE 0 END) AS sum_amount_prior, SUM(CASE WHEN datetime < TIMESTAMP '2017-04-01' THEN 1 ELSE 0 END) AS transaction_count_prior FROM transactions WHERE datetime BETWEEN TIMESTAMP '2017-01-01' AND '2017-05-01' GROUP BY customer El resultado de esta consulta es: customer sum_amount _after transaction _count_after sum _amount_prior transaction _count_prior 2 610 2 460 3 1 410 2 300 3 3 610 2 350 1 Espera, ¿cómo ha funcionado? Esta larga consulta puede ser confusa, así que vamos a desglosarla un poco. Nos concentraremos primero en la parte que tiene que ver con el corte del 1 de abril (2017-04-01). 👾 [NUEVO] ¿Qué pasa cuando combinas #CASE con las sentencias modificadoras de #datos de #SQL? ¡¡¡Descúbrelo!!! ➽ https://t.co/7IuBoDT85z... pic.twitter.com/wNiDiv5hSa - Vertabelo (@Vertabelo) 6 de junio de 2017 A continuación, estamos viendo el importe de la transacción para el cliente "1". Cualquier importe de transacción que se haya contabilizado antes del 01.04.2017 se pondrá a "0". Llamaremos a esta columna amount_after. SELECT customer, datetime, CASE WHEN datetime >= TIMESTAMP '2017-04-01' THEN amount ELSE 0 END AS amount_after, amount FROM transactions WHERE datetime BETWEEN TIMESTAMP '2017-01-01' AND '2017-05-01' AND customer = '1' ORDER BY datetime; customer datetime amount_after amount 1 2017-01-01 00:00:00.000000 0 100 1 2017-02-01 00:00:00.000000 0 50 1 2017-03-01 00:00:00.000000 0 150 1 2017-04-01 00:00:00.000000 200 200 1 2017-05-01 00:00:00.000000 210 210 Alternativamente, podemos reemplazar los ceros mostrados en los resultados con un NULL en la sentencia ELSE: SELECT customer, datetime, CASE WHEN datetime >= TIMESTAMP '2017-04-01' THEN amount ELSE null END AS amount_after, amount FROM transactions WHERE datetime BETWEEN TIMESTAMP '2017-01-01' AND '2017-05-01' AND customer = '1' ORDER BY datetime; customer datetime amount_after amount 1 2017-01-01 00:00:00.000000 100 1 2017-02-01 00:00:00.000000 50 1 2017-03-01 00:00:00.000000 150 1 2017-04-01 00:00:00.000000 200 200 1 2017-05-01 00:00:00.000000 210 210 Ahora si resumimos estas columnas, obtendremos: El total de todas las transacciones de sum(amount). La suma de todas las transacciones que se contabilizaron después del 01.04. Cualquier transacción que se haya contabilizado antes del 01.04 se pone a cero (o NULL) para sum(amount_after). Si queremos contar cuántas transacciones se contabilizaron después del 01.04, podemos modificar la consulta y crear una sentencia COUNT que utilice el mismo CASE con NULL en el ELSE. SELECT customer, count(CASE WHEN datetime >= TIMESTAMP '2017-04-01' THEN amount ELSE NULL END) AS count_after FROM transactions WHERE datetime BETWEEN TIMESTAMP '2017-01-01' AND '2017-05-01' GROUP BY customer ORDER BY customer; customer count_after 1 2 2 2 3 2 Nota: Esta consulta es realmente rápida, ya que el RDBMS sólo necesita acceder a una tabla. Construir consultas de agregación que usen sólo una tabla es una buena manera de obtener resultados rápidamente. Pruebe a utilizar CASE con un cero en la sentencia COUNT. ¿Cuál es el resultado y por qué? Cuéntanoslo en la sección de comentarios más abajo. Tags: funciones de agregado CASE resumen condicional Patrones de SQL