Agregación y agrupación en SQL

Aprende a responder preguntas de resumen a partir de una tabla de base de datos: cuántos, cuánto, en promedio, el menor y el mayor. Utiliza COUNT, SUM, AVG, MIN y MAX, agrupa filas con GROUP BY para obtener un resultado por categoría y conserva solo los grupos que necesitas con HAVING. También aprenderás cómo cambian los resultados con los valores ausentes y la división entera, cómo redondear promedios y porcentajes, y cómo comprobar que una consulta de resumen devuelve las cifras correctas. Los ejemplos utilizan SQL estándar que funciona en SQLite y PostgreSQL, y señalan las diferencias con MySQL, SQL Server y Oracle cuando son relevantes.

PrincipianteUnidad 4 de 6 del curso Curso de Fundamentos de SQL

Lo que aprenderás

  1. Utiliza COUNT, SUM, AVG, MIN y MAX para convertir muchas filas en valores de resumen, elegir el tipo de recuento adecuado y predecir cómo cambian un resultado los valores ausentes.
    • Obtén totales, promedios y valores mínimos y máximos
      Utiliza SUM, AVG, MIN y MAX sobre una tabla completa o sobre las filas que conserva una cláusula WHERE, y combina varias de estas funciones en una consulta.
    • Cuenta filas, valores y valores distintos
      Elige entre COUNT(*), COUNT(column) y COUNT(DISTINCT column), y comprende cómo trata cada uno los valores repetidos y ausentes.
    • Predice cómo afectan los valores NULL a las funciones de agregación
      Comprende que las funciones de agregación omiten los valores NULL, predice los resultados para conjuntos de entrada vacíos y sustituye NULL por un valor predeterminado cuando la pregunta lo requiera.
  2. Utiliza GROUP BY para obtener una fila de resumen por categoría, por combinación de valores o por valor calculado, y aplica la regla que determina qué puede mostrar una consulta agrupada.
    • Resume cada categoría con GROUP BY
      Divide una tabla en grupos que comparten un valor, calcula funciones de agregación por grupo y ordena y limita el resultado agrupado.
    • Aplica la regla que determina qué puede mostrar una consulta agrupada
      Comprende qué columnas pueden aparecer en la lista SELECT de una consulta agrupada, corrige el error que aparece cuando se incumple la regla y reconoce las diferencias entre bases de datos.
    • Agrupa por varias columnas y por valores calculados
      Agrupa filas por combinaciones de columnas y por expresiones, como el mes de una fecha o una categoría definida con CASE, e interpreta el resultado más detallado.
  3. Conserva solo los grupos cuyos totales, recuentos o promedios cumplen una condición, y decide si una condición corresponde a WHERE o a HAVING.
    • Conserva los grupos que cumplen una condición
      Escribe condiciones HAVING sobre valores de agregación, incluidos los que no se muestran, para filtrar un resultado agrupado.
    • Elige entre WHERE y HAVING
      Utiliza el orden lógico de una consulta para decidir si una condición filtra filas o grupos, y predice cómo cambia el resultado esa elección.
  4. Evita la división entera, comprende qué tipo de número devuelve cada función de agregación y redondea promedios, totales y porcentajes en el momento adecuado.
    • Evita la división entera en promedios y porcentajes
      Reconoce cuándo la división de resultados de agregación pierde los decimales, corrígela con un operando decimal y comprende las diferencias entre los tipos de resultado de las bases de datos.
    • Redondea los resultados de agregación
      Redondea promedios, totales y porcentajes con ROUND, hazlo en el momento adecuado y gestiona las diferencias entre SQLite y PostgreSQL.
  5. Combina CASE con funciones de agregación para obtener recuentos, totales y porcentajes condicionales, y convierte una pregunta en una consulta agrupada cuyas cifras puedas comprobar.
    • Cuenta y suma según una condición con CASE
      Coloca una expresión CASE dentro de una función de agregación para calcular varios recuentos, totales y porcentajes condicionales en una consulta agrupada.
    • Construye y comprueba una consulta de resumen a partir de una pregunta
      Convierte una pregunta de negocio en una consulta agrupada paso a paso, evita confundir los niveles de detalle y comprueba que las cifras sean correctas.

Guía de estudio de Agregación y agrupación en SQL

5 capítulos

1

Resume datos con funciones de agregación

Una tabla registra hechos individuales; un informe suele necesitar unas pocas cifras que los describan en conjunto. Las funciones de agregación convierten filas en recuentos, totales, promedios y valores extremos. Elegir la función es solo parte del trabajo: también debes decidir qué filas entran en el cálculo y qué significan los valores ausentes. Utilizaremos una pequeña tabla de pedidos para comprobar cada respuesta a mano antes de confiar en la consulta.

1.1 Obtén totales, promedios y valores mínimos y máximos

Una función de agregación combina valores de muchas filas en un resultado. Oracle también la llama función de grupo. Sin GROUP BY, una consulta de agregación trata todas las filas que pasan WHERE como un grupo y devuelve una fila de resumen.

Empieza con datos que puedas comprobar

Cada fila de orders es un pedido. Las columnas numéricas siguientes contienen números enteros; order_id es la clave primaria. Las fechas utilizan texto ISO en SQLite y el tipo DATE en PostgreSQL.

order_idcustomerregionamountquantitydiscountorder_date
1AnaEast1202102026-01-05
2BenWest801NULL2026-01-17
3AnaEast45352026-02-02
4ChenNorth2004NULL2026-02-14
5BenWest60102026-02-20
6DaraEast952NULL2026-03-03
7ChenNorth1505152026-03-09
8EliNULL301NULL2026-03-21
Elige la medida

SUM(amount) suma los importes. AVG(amount) da su media aritmética. MIN(amount) encuentra el importe mínimo y MAX(amount) encuentra el máximo. Puedes solicitar las cuatro en una consulta:

SELECT SUM(amount) AS total, AVG(amount) AS avg_amount, MIN(amount) AS smallest, MAX(amount) AS largest FROM orders;

El resultado es una fila: total 780, promedio 97,5, mínimo 30 y máximo 200. Suma los ocho importes para obtener 780 y después divide entre ocho para obtener 97,5. Cada función utiliza las mismas ocho filas de entrada. Los alias claros después de AS hacen que los encabezados de salida sean útiles; un encabezado generado como sum dice poco sobre lo que se ha sumado.

Filtra antes de calcular

Para resumir los pedidos de East, escribe SELECT COUNT(*) AS orders, SUM(amount) AS total FROM orders WHERE region = 'East';. El filtro conserva los importes 120, 45 y 95. La consulta devuelve tres pedidos y un total de 260. WHERE elige las filas de entrada antes de ejecutar cualquier función de agregación.

Una función de agregación también puede recibir una expresión calculada. En una tabla con quantity y unit_price, SUM(quantity * unit_price) primero calcula los ingresos de cada fila y después los suma. Dos filas, dos artículos a 5 y tres artículos a 10, aportan 10 y 30, para un total de 40. En cambio, SUM(quantity) * SUM(unit_price) multiplica 5 por 15 y da 75. Mantener el cálculo dentro de SUM conserva la correspondencia entre cada cantidad y su precio.

Interpreta correctamente los valores extremos

MIN(order_date) es 2026-01-05 y MAX(order_date) es 2026-03-21. Los valores de fecha y el texto de fecha ISO se ordenan cronológicamente. Un texto como «03/21/2026» sigue el orden de los caracteres, que no coincide de forma fiable con el orden de las fechas. Los valores extremos de texto también siguen la intercalación de la base de datos, sus reglas para comparar texto. Aquí los clientes extremos son «Ana» y «Eli»; mezclar mayúsculas y minúsculas puede cambiar la ordenación del texto.

MAX(amount) devuelve un importe, no el pedido completo que lo contiene. Para mostrar un cliente con un pedido de importe máximo, utiliza SELECT customer, amount FROM orders ORDER BY amount DESC LIMIT 1;. PostgreSQL rechaza una columna customer sin agregar junto a MAX(amount) sin una agrupación adecuada. SQLite tiene una regla especial para un único MIN o MAX que puede devolver una columna contigua de la fila extrema, pero los extremos empatados siguen necesitando una regla de desempate.

Puntos clave

  • Una función de agregación devuelve un valor para un conjunto de filas.
  • WHERE selecciona las filas que utiliza la función de agregación.
  • Calcula la aportación de cada fila dentro de SUM cuando los valores deban mantenerse emparejados.
  • MIN y MAX siguen el orden numérico, de fechas o de texto.
  • Un valor extremo no identifica una fila completa.

1.2 Cuenta filas, valores y valores distintos

«¿Cuántos?» puede preguntar por filas, valores registrados o valores diferentes. Son recuentos distintos, aunque en una tabla pequeña puedan dar por casualidad el mismo número.

Tres formas de COUNT
ExpresiónQué cuenta
COUNT(*)Todas las filas de entrada
COUNT(region)Filas con una región que no es NULL
COUNT(DISTINCT region)Valores diferentes de región que no son NULL

En la tabla de pedidos, las regiones son East, West, East, North, West, East, North y NULL. SELECT COUNT(*) AS order_rows, COUNT(region) AS with_region, COUNT(DISTINCT region) AS regions FROM orders; devuelve 8, 7 y 3. Los nombres de región repetidos se cuentan por separado en COUNT(region), pero cada nombre contribuye solo una vez al recuento de valores distintos.

Para «¿Cuántos clientes diferentes hicieron pedidos?», utiliza COUNT(DISTINCT customer). Ana, Ben y Chen aparecen dos veces cada uno, mientras que Dara y Eli aparecen una vez, por lo que la respuesta es cinco clientes. COUNT(customer) devuelve ocho porque todos los pedidos indican un cliente. Mide filas de pedido que indican un cliente, no personas.

Un cero registrado también cuenta

Los descuentos son 10, NULL, 5, NULL, 0, NULL, 15 y NULL. COUNT(discount) devuelve cuatro. El cero registra un valor conocido y cuenta igual que 10, 5 y 15. Una cadena vacía también es un valor en SQLite y PostgreSQL; Oracle trata una cadena vacía como NULL.

Resta el recuento de valores que no son NULL del recuento de filas para medir los registros sin ese dato: SELECT COUNT(*) - COUNT(region) AS missing_region FROM orders; devuelve uno. Esto funciona porque ambos recuentos utilizan exactamente las mismas filas de entrada.

Listas de valores distintos y recuentos de valores distintos

SELECT DISTINCT region FROM orders; enumera East, West, North y una fila NULL. Su función es devolver valores diferentes, y NULL permanece en esa lista. COUNT(DISTINCT region) devuelve tres porque el recuento ignora NULL. No deduzcas un recuento de valores distintos contando una lista sin haber decidido si debe incluir su fila NULL.

DISTINCT también puede aparecer dentro de SUM o AVG. Las cantidades son 2, 1, 3, 4, 1, 2, 5 y 1. Su suma normal es 19. SUM(DISTINCT quantity) conserva solo 1, 2, 3, 4 y 5, lo que da 15. Las cantidades repetidas suelen describir ventas adicionales reales. Eliminarlas cambia la medida; no corrige registros duplicados.

Cuenta combinaciones en dos pasos

Para obtener pares diferentes de región y cliente, crea primero una lista sin duplicados:

SELECT COUNT(*) FROM (SELECT DISTINCT region, customer FROM orders) AS pairs;

La consulta interna devuelve cinco pares: East/Ana, East/Dara, North/Chen, West/Ben y NULL/Eli. El COUNT(*) externo cuenta esas cinco filas, incluida NULL/Eli. Esta forma funciona en SQLite y PostgreSQL. MySQL también acepta COUNT(DISTINCT region, customer), pero esa forma excluye las combinaciones que contienen NULL, por lo que puede responder otra pregunta. En SQLite y PostgreSQL, la forma separada por comas no es válida.

Por último, un recuento nunca devuelve NULL. SELECT COUNT(*) FROM orders WHERE region = 'South'; devuelve una fila de resumen que contiene cero, porque no hay pedidos que coincidan.

Puntos clave

  • Elige entre filas, valores registrados y valores registrados diferentes.
  • El cero es un valor registrado, por lo que COUNT(column) lo incluye.
  • Una lista de valores distintos puede incluir NULL; COUNT(DISTINCT column) lo omite.
  • SUM(DISTINCT x) elimina valores repetidos, incluidas las repeticiones legítimas.
  • Cuenta combinaciones distintas contando las filas de un resultado interno sin duplicados.
  • COUNT devuelve cero para un conjunto de entrada vacío.

1.3 Predice cómo afectan los valores NULL a las funciones de agregación

NULL significa que un valor está ausente o es desconocido. Cambia los valores que recibe una función de agregación, por lo que un total o promedio puede ser válido en SQL y, aun así, medir algo diferente de lo que pretendías.

Determina el denominador

Supón que scores contiene Ana 80, Ben NULL, Chen 70 y Dara 90. SUM(score) es 240, COUNT(score) es tres y COUNT(*) es cuatro. AVG(score) es 80: las tres calificaciones registradas suman 240 y se dividen entre tres.

Las cinco funciones de agregación estándar ignoran los argumentos NULL. COUNT(*) cuenta todas las filas porque no evalúa un argumento de columna. MIN(score) es 70 y MAX(score) es 90; NULL no se convierte en la calificación mínima ni en la máxima. Esto difiere de la ordenación, en la que los valores NULL ocupan un extremo del resultado: al principio en una ordenación ascendente de SQLite y al final en una ordenación ascendente de PostgreSQL.

Un promedio calculado manualmente necesita el recuento de valores que no son NULL: 1.0 * SUM(score) / NULLIF(COUNT(score), 0). El operando decimal conserva los resultados fraccionarios, y NULLIF convierte en NULL un divisor cero. Dividir entre COUNT(*) daría 60 y, en la práctica, trataría la calificación ausente como cero.

Decide qué significa un valor predeterminado

COALESCE devuelve el primer argumento que no es NULL. Si Ben aún no ha sido calificado, deja su calificación ausente y calcula el promedio de los resultados conocidos. Si la ausencia a un examen se registra como NULL pero debe contar como cero, AVG(COALESCE(score, 0)) calcula el promedio de 80, 0, 70 y 90, que da 60. El significado de los datos determina si esa sustitución está justificada.

Compara colocar COALESCE dentro y fuera de una función. AVG(COALESCE(score, 0)) cambia los valores que entran en el promedio. COALESCE(AVG(score), 0) cambia solo un resultado final NULL; sigue dando 80 para estas calificaciones. NVL(x, 0) de Oracle es otra forma con dos argumentos para sustituir NULL.

Distingue entre ausencia de filas y ausencia de valores registrados

Con WHERE region = 'South', no queda ningún pedido. Una consulta de agregación sin GROUP BY sigue devolviendo una fila: COUNT(*) es cero, mientras que SUM(amount), AVG(amount), MIN(amount) y MAX(amount) son NULL. Para mostrar un total vacío como cero, utiliza COALESCE(SUM(amount), 0). SQLite también ofrece TOTAL(amount), que devuelve 0,0 para un conjunto de entrada vacío.

Ahora conserva los cuatro pedidos cuyo descuento es NULL. Hay filas, pero no hay valores de descuento registrados: COUNT(*) es cuatro, COUNT(discount) es cero y SUM(discount) es NULL. Cero valores registrados y cuatro valores ausentes son observaciones diferentes.

Comprueba las expresiones antes de que entren en SUM

Las operaciones aritméticas con NULL producen NULL. En SUM(amount - discount), los cuatro pedidos sin un descuento registrado no aportan ningún valor. Solo contribuyen las filas con descuento conocido: 110, 40, 60 y 135, que suman 345.

Si un descuento ausente significa que no hay descuento, escribe SUM(amount - COALESCE(discount, 0)). Así contribuyen todos los pedidos; el importe total de 780 menos los descuentos registrados de 30 da 750. Envolver toda la suma en COALESCE no recuperaría los pedidos omitidos, porque 345 ya es un valor que no es NULL.

Para localizar valores ausentes, utiliza IS NULL o IS NOT NULL. WHERE discount IS NULL encuentra cuatro pedidos. discount = NULL nunca es verdadero y, por tanto, no puede seleccionarlos.

Puntos clave

  • AVG(x) divide entre el número de valores que no son NULL.
  • Un COALESCE interno cambia los valores de entrada; uno externo cambia un resultado NULL.
  • Un conjunto de entrada vacío da cero para COUNT y NULL para las otras cuatro funciones de agregación.
  • NULL dentro de una expresión aritmética puede eliminar la aportación de una fila.
2

Agrupa filas y resume cada grupo

Un total de toda la tabla responde una pregunta, pero muchos informes piden un resultado por cliente, región o mes. La agrupación establece ese nivel de detalle antes de ejecutar las funciones de agregación. Seguirás cómo las filas se convierten en grupos, elegirás columnas que puedan describir un grupo completo y verás cómo cambia el informe al añadir una columna de agrupación. Después, la ordenación decide cómo presentar los resultados; la agrupación por sí sola no les da un orden.

2.1 Resume cada categoría con GROUP BY

GROUP BY reúne filas que comparten un valor de agrupación. Cada función de agregación se ejecuta por separado dentro de cada grupo, y la salida contiene una fila por cada grupo que existe después del filtrado.

Decide qué significa una fila del resultado

«Ventas totales por región» pide una fila de salida por región. Empieza escribiendo esa frase y después utiliza region como columna de agrupación:

SELECT region, COUNT(*) AS orders, SUM(amount) AS total FROM orders GROUP BY region;

Los tres importes de East, 120, 45 y 95, forman un grupo. Su recuento es tres y su total es 260. North tiene dos pedidos que suman 350; West tiene dos que suman 140. El pedido de Eli forma un grupo de región NULL con un pedido que suma 30. Hay cuatro filas de resultado, no ocho.

Lee la consulta como una secuencia: FROM aporta pedidos, cualquier WHERE elimina filas, GROUP BY reúne las filas restantes por región y las funciones de agregación resumen cada conjunto. SELECT muestra su etiqueta y sus medidas. La agrupación no descarta los pedidos menores dentro de un grupo; todos contribuyen salvo que un filtro de filas los haya eliminado.

Mantén visibles las categorías ausentes

Las filas con NULL en la columna de agrupación pertenecen a un grupo NULL. Esto es útil: un informe puede mostrar cuánta actividad no tiene una región registrada. No trata cada región ausente como una categoría diferente.

Para mostrar una etiqueta legible, selecciona COALESCE(region, 'No region') AS region_label y conserva GROUP BY region. La etiqueta cambia el valor mostrado. Para excluir esas filas de los cálculos, añade WHERE region IS NOT NULL antes de GROUP BY. Los totales resultantes suman 750, porque se ha excluido el importe de 30 de Eli.

Una consulta agrupada sobre un conjunto de entrada sin filas no devuelve grupos. Por ejemplo, filtrar la tabla para South y después agrupar por región no devuelve filas de resultado. Eso difiere de una agregación de toda la tabla sin GROUP BY, que produce una fila de resumen incluso con un conjunto de entrada vacío.

Ordena los grupos de forma explícita

GROUP BY no garantiza ningún orden de salida. Para enumerar primero las regiones con los mayores totales, añade ORDER BY total DESC. El alias total está permitido en ORDER BY; ORDER BY SUM(amount) DESC da la misma ordenación.

Un informe de clientes puede seleccionar los tres totales más altos:

SELECT customer, SUM(amount) AS total FROM orders GROUP BY customer ORDER BY total DESC, customer LIMIT 3;

Devuelve Chen 350, Ana 165 y Ben 140. La segunda clave de ordenación, customer, da a los totales empatados un orden reproducible. LIMIT 3 devuelve solo tres filas; no conserva todos los empates en el límite. SQL Server expresa este límite con SELECT TOP 3, mientras que Oracle admite FETCH FIRST 3 ROWS ONLY.

Al ordenar las etiquetas de categoría de forma ascendente, SQLite normalmente coloca NULL al principio y PostgreSQL lo coloca al final. Especifica la ordenación deseada cuando la posición sea relevante.

Comprueba la columna de agrupación

SELECT DISTINCT region FROM orders y SELECT region FROM orders GROUP BY region devuelven las mismas etiquetas de región distintas, incluido NULL. Utiliza la agrupación cuando también necesites una medida para cada etiqueta.

Agrupar por el valor único order_id da ocho grupos de una fila cada uno. Todos los recuentos son uno, y cada total de importes equivale al importe original. Para un informe regional, ese resultado indica que la columna de agrupación es demasiado detallada.

Puntos clave

  • Indica qué representa una fila de salida antes de elegir GROUP BY.
  • Todos los valores NULL de agrupación forman un grupo.
  • Utiliza ORDER BY para establecer el orden del resultado y una segunda clave para resolver empates.
  • Agrupar por una clave única de fila deja grupos de una fila.

2.2 Aplica la regla que determina qué puede mostrar una consulta agrupada

Un informe agrupado tiene que reunir muchas filas de entrada en una fila de resultado. Por tanto, cada valor mostrado necesita un significado claro para todo el grupo. Por eso SQL restringe las columnas que puedes seleccionar.

Sigue la regla de agrupación compatible con distintas bases de datos

Un elemento de un SELECT agrupado debe ser una columna de agrupación, una expresión construida a partir de columnas de agrupación, una función de agregación o una constante. Considera:

SELECT region, customer, COUNT(*) FROM orders GROUP BY region;

East contiene Ana, Ana y Dara. El grupo tiene una región y un recuento, pero dos nombres de cliente diferentes. La consulta no ha indicado qué cliente debe mostrar el único resultado de East. PostgreSQL rechaza la columna customer sin agrupar.

El mismo problema aparece sin GROUP BY: SELECT customer, SUM(amount) FROM orders combina un total de toda la tabla con un nombre individual. El total no tiene una única etiqueta de cliente.

Corrige la consulta para que responda la pregunta

Hay tres correcciones útiles, cada una con un significado diferente:

  • Para obtener una fila por región, elimina customer: SELECT region, COUNT(*) FROM orders GROUP BY region;.
  • Para obtener una fila por región y cliente, agrupa por ambos: SELECT region, customer, COUNT(*) FROM orders GROUP BY region, customer;.
  • Para obtener el número de clientes por región, aplica una función de agregación a los nombres: SELECT region, COUNT(DISTINCT customer) AS customers FROM orders GROUP BY region;.

La última consulta muestra dos clientes en East y uno en cada uno de los demás grupos de región. Añadir una columna a GROUP BY puede cambiar el nivel de detalle del informe, así que elige la corrección según la pregunta, no solo según el mensaje de error.

Una columna de agrupación puede omitirse de SELECT. SELECT COUNT(*) FROM orders GROUP BY region; es válida y devuelve cuatro recuentos: tres, dos, dos y uno, sin un orden garantizado. Es difícil utilizar esas cifras sin sus etiquetas de región.

Aplica la regla más allá de SELECT

Un ORDER BY customer agrupado presenta el mismo problema al agrupar solo por región: ¿qué cliente debe determinar la posición de East? Las condiciones HAVING de una consulta agrupada también deben describir un grupo completo. Utiliza en ellas columnas agrupadas o expresiones de agregación.

Reconoce el comportamiento permisivo de algunas bases de datos

SQLite acepta una columna sin agrupar ni agregar, una columna seleccionada que no está agrupada ni se utiliza en una función de agregación. Toma un valor de una fila de entrada del grupo. Un resultado aparentemente correcto, como «Ana» junto a East, no significa que Ana represente todos los pedidos de esa región.

Con exactamente una función de agregación incorporada MIN o MAX, SQLite toma los valores sin agrupar ni agregar de una fila que contiene el extremo. Los empates y la presencia de varias funciones de extremos hacen incierta la fila seleccionada. Este atajo es específico de esa base de datos. Ordenar las filas originales es más claro cuando quieres un pedido con un importe extremo.

El modo predeterminado ONLY_FULL_GROUP_BY de MySQL rechaza los valores sin agrupar que el grupo no determina. ANY_VALUE(customer) permite explícitamente un valor arbitrario, pero no encuentra el cliente asociado a un total elegido. SQL Server y Oracle también rechazan las columnas ordinarias sin agrupar.

PostgreSQL y MySQL reconocen una excepción para la clave primaria: agrupar por la clave primaria de una tabla identifica una sola fila, por lo que sus demás columnas quedan determinadas. SELECT order_id, customer, SUM(amount) FROM orders GROUP BY order_id funciona en PostgreSQL. Incluir en GROUP BY todas las columnas mostradas sin agregar sigue siendo el enfoque compatible con distintas bases de datos.

Puntos clave

  • Cada valor mostrado debe describir el grupo completo.
  • Eliminar una columna, agrupar por ella o aplicarle una función de agregación responde preguntas diferentes.
  • La regla de agrupación también se aplica a HAVING y ORDER BY en consultas agrupadas.
  • Las columnas sin agrupar ni agregar que acepta SQLite pueden ocultar un informe incorrecto.
  • Una clave primaria agrupada determina las demás columnas de su fila.

2.3 Agrupa por varias columnas y por valores calculados

Algunos informes necesitan una combinación de categorías o una categoría calculada a partir de cada fila. SQL puede agrupar por varias columnas o por una expresión. La decisión importante sigue siendo qué representa una fila de salida.

Agrupa por una combinación

GROUP BY region, customer reúne filas solo cuando coinciden ambos valores. En la tabla de pedidos, ejecuta:

SELECT region, customer, COUNT(*) AS orders, SUM(amount) AS total FROM orders GROUP BY region, customer ORDER BY region, customer;

Los resultados son East/Ana: dos pedidos, 165; East/Dara: uno, 95; North/Chen: dos, 350; West/Ben: dos, 140; y NULL/Eli: uno, 30. Los dos resultados de East suman el total regional de 260.

Agrupar por customer, region forma las mismas combinaciones. El orden de las columnas en GROUP BY no ordena la salida. El ORDER BY separado de arriba elige cómo mostrarla, según la posición predeterminada de NULL en cada base de datos.

Solo aparecen las combinaciones presentes en los datos de entrada. No hay una fila West/Ana con un recuento de cero. La agrupación resume filas existentes; no genera todos los emparejamientos posibles de etiquetas de categoría.

Añade detalle solo cuando sea necesario

Añadir una columna divide un grupo solo si sus filas contienen valores diferentes en esa columna. Aquí, agrupar solo por cliente ya da cinco grupos. Añadir la región sigue dando cinco, porque cada cliente tiene un solo valor de región. Añadir order_date a un informe regional crea grupos menores para las distintas fechas y cambia la pregunta que se responde.

Agrupa fechas por año y mes

En SQLite, utiliza strftime('%Y-%m', order_date) para crear una etiqueta como «2026-02»:

SELECT strftime('%Y-%m', order_date) AS month, COUNT(*) AS orders, SUM(amount) AS total FROM orders GROUP BY strftime('%Y-%m', order_date) ORDER BY month;

Enero tiene dos pedidos que suman 200, febrero tiene tres que suman 305 y marzo tiene tres que suman 275. En PostgreSQL, sustituye las dos apariciones de strftime('%Y-%m', order_date) por to_char(order_date, 'YYYY-MM') para una columna DATE.

Agrupar solo por el número de mes combina el mismo mes de distintos años. Enero de 2025 y enero de 2026 se convertirían en un grupo. Mantener el año en la expresión de agrupación conserva separados los meses de cada año.

Repetir la expresión en GROUP BY hace explícita la agrupación. SQLite, PostgreSQL y MySQL también aceptan el alias de salida, como GROUP BY month; SQL Server no acepta ahí un alias de SELECT del mismo nivel.

Crea categorías con CASE

Una expresión CASE puede asignar una etiqueta a cada pedido antes de agrupar:

SELECT CASE WHEN amount >= 100 THEN 'large' ELSE 'small' END AS size, COUNT(*) AS orders, SUM(amount) AS total FROM orders GROUP BY CASE WHEN amount >= 100 THEN 'large' ELSE 'small' END;

La categoría large contiene 120, 200 y 150: tres pedidos que suman 470. La categoría small contiene cinco pedidos que suman 310. El umbral es inclusivo, por lo que un importe de exactamente 100 pertenece a «large». La misma expresión CASE aparece en la presentación y en la agrupación para que ambas utilicen la misma definición de categoría.

Puntos clave

  • Varias columnas de agrupación identifican combinaciones que aparecen en los datos.
  • Añadir una columna solo divide los grupos en los que esa columna varía.
  • Incluye el año además del mes para separar los meses de cada año.
  • Utiliza la misma expresión de categoría en la etiqueta seleccionada y en la agrupación.
  • GROUP BY no crea combinaciones ausentes con recuentos de cero.
  • El orden de las columnas de agrupación no controla el orden de salida.
3

Filtra resultados agrupados con HAVING

El filtrado puede cambiar las filas utilizadas en un cálculo o decidir qué resúmenes terminados aparecen en un informe. Esas decisiones responden preguntas diferentes. Utilizarás HAVING para conservar grupos según su recuento, total o promedio, y después lo combinarás con WHERE sin cambiar el significado previsto. Seguir el orden lógico de una consulta facilita colocar cada condición y predecir el resultado antes de ejecutar SQL.

3.1 Conserva los grupos que cumplen una condición

HAVING comprueba los grupos después de calcular sus funciones de agregación. Utilízalo para una petición como «regiones con ventas totales superiores a 200». La condición describe cada total regional, no un pedido individual.

Primero calcula, después conserva los grupos

SELECT region, COUNT(*) AS orders, SUM(amount) AS total FROM orders GROUP BY region HAVING SUM(amount) > 200;

Antes de HAVING, los totales regionales son East 260, North 350, West 140 y NULL 30. La condición conserva East con tres pedidos y North con dos. Elimina los otros dos grupos del resultado; no elimina pedidos concretos del interior de East o North.

En SQL escrito, coloca HAVING después de GROUP BY y antes de ORDER BY. La ordenación se aplica después a los grupos que han superado la condición.

Filtra por medidas que no muestras

SELECT region FROM orders GROUP BY region HAVING COUNT(*) >= 2; devuelve East, North y West. La base de datos puede contar las filas de un grupo para decidir si cumple la condición sin mostrar ese recuento. HAVING y SELECT no necesitan listas de funciones de agregación idénticas.

Puedes combinar condiciones de grupo. HAVING COUNT(*) >= 2 AND AVG(amount) > 80 conserva East y North. East tiene tres pedidos y un promedio aproximado de 86,67; North tiene dos y un promedio de 175. West tiene suficientes pedidos, pero su promedio es solo 70. Deben cumplirse ambas condiciones porque están unidas con AND; OR permitiría que se cumpliera cualquiera de las dos.

Encuentra valores repetidos

Agrupar y contar también permite encontrar duplicados:

SELECT customer, COUNT(*) AS orders FROM orders GROUP BY customer HAVING COUNT(*) > 1;

Ana, Ben y Chen tienen dos pedidos cada uno y cumplen la condición. Dara y Eli tienen uno y no la cumplen. Para encontrar valores de correo electrónico repetidos en una tabla de clientes, el mismo patrón agrupa por email y conserva los recuentos superiores a uno. El recuento es el número de registros que comparten ese valor.

Utiliza la expresión que necesita la condición

Repite la función de agregación en HAVING: HAVING SUM(amount) > 200. PostgreSQL y SQL estándar no permiten el alias de salida total en esa condición del mismo nivel, aunque SQLite y MySQL sí lo permiten. Un alias es válido en un ORDER BY total DESC posterior.

Un valor redondeado mostrado y el valor comprobado pueden diferir. El promedio exacto de East es 260 dividido entre tres. Si seleccionas ROUND(AVG(amount), 2) pero escribes HAVING AVG(amount) > 86.67, East se elimina: su promedio sin redondear es inferior a 86,67. North permanece. La condición utiliza exactamente la expresión escrita en HAVING. Solo HAVING ROUND(AVG(amount), 2) ... comprobaría el valor redondeado.

Filtra el único grupo global

HAVING también puede funcionar sin un GROUP BY explícito. SELECT COUNT(*) FROM orders HAVING COUNT(*) > 5; trata los ocho pedidos como un grupo, supera la comprobación y devuelve una fila que contiene ocho. Sustituir la condición por COUNT(*) > 10 no devuelve filas, en lugar de devolver una fila que contenga cero.

PostgreSQL admite este patrón, al igual que SQLite desde la versión 3.39.0. En una instalación anterior de SQLite, una consulta que utiliza HAVING necesita un GROUP BY explícito.

Puntos clave

  • HAVING conserva o elimina grupos ya calculados.
  • Una función de agregación de HAVING no tiene que aparecer en SELECT.
  • Combina condiciones de grupo con AND, OR y NOT.
  • Repite las expresiones de agregación en HAVING para obtener consultas compatibles con distintas bases de datos.
  • Una condición comprueba su propia expresión, que puede estar sin redondear.

3.2 Elige entre WHERE y HAVING

Una condición corresponde al punto en el que existe lo que describe. Los pedidos individuales existen antes de la agrupación. Un total regional existe solo después de agrupar y sumar los pedidos.

Sigue el orden lógico

SQL se escribe como SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT. Para razonar sobre el resultado, sigue este orden lógico:

  1. FROM aporta las filas.
  2. WHERE conserva las filas que cumplen la condición.
  3. GROUP BY forma grupos y las funciones de agregación calculan sus medidas.
  4. HAVING conserva los grupos que cumplen la condición.
  5. SELECT produce los valores de salida; DISTINCT elimina las filas de salida duplicadas si se solicita.
  6. ORDER BY ordena el resultado y LIMIT conserva el número de filas solicitado.

La base de datos puede organizar su ejecución interna de otra manera.

Coloca cada condición en su nivel
PeticiónCláusula
Pedidos con amount >= 60WHERE
Pedidos en un intervalo de fechas determinadoWHERE
Regiones con SUM(amount) > 200HAVING
Clientes con más de un pedidoHAVING COUNT(*) > 1

WHERE SUM(amount) > 200 falla porque el total aún no existe en la etapa de filtrado de filas. Una condición de fila como region = 'East' puede resolverse antes de agrupar y corresponde a WHERE.

Recorre ambos filtros

SELECT region, COUNT(*) AS orders, SUM(amount) AS total FROM orders WHERE amount >= 60 GROUP BY region HAVING SUM(amount) > 200;

Primero elimina los pedidos de 45 y 30. East contiene ahora 120 y 95, North contiene 200 y 150, y West contiene 80 y 60. Después calcula los totales de 215, 350 y 140. Por último, conserva los totales superiores a 200. La salida es East con dos pedidos y 215, y North con dos y 350. La región NULL no tiene filas restantes, por lo que nunca forma un grupo.

No cambies la pregunta al mover un filtro

«Para cada región, calcula el promedio solo de los pedidos de 60 o más» utiliza WHERE amount >= 60. El promedio de East pasa a ser 107,5 a partir de 120 y 95.

HAVING MIN(amount) >= 60 pide las regiones en las que todos los importes que no son NULL alcanzan el umbral. East se elimina porque su mínimo es 45; North y West permanecen con sus pedidos originales. Mover la comprobación cambió el significado: de seleccionar pedidos individuales a aceptar o rechazar regiones completas.

Para este informe regional, region <> 'West' da el mismo resultado en WHERE o en HAVING: East y North permanecen, y el grupo NULL tampoco supera la comparación. WHERE expresa la restricción de filas directamente y la aplica antes de agrupar. Para conservar también las regiones ausentes, la condición necesita un OR region IS NULL explícito.

Los alias de SELECT no están disponibles en las cláusulas anteriores WHERE y HAVING en PostgreSQL. SQLite permite un uso más amplio de alias, pero escribir la columna o expresión de entrada completa deja clara la etapa prevista.

Puntos clave

  • WHERE cambia los valores de entrada de las funciones de agregación; HAVING filtra sus resultados.
  • Coloca en HAVING las condiciones sobre el recuento, total o promedio de un grupo.
  • Al predecir un resultado, sigue el filtrado de filas antes de la agrupación.
  • Una comprobación del mínimo de un grupo puede eliminar el grupo completo.
4

Calcula resultados exactos y correctamente redondeados

Una consulta puede elegir las filas correctas y aun así perder la parte fraccionaria de su respuesta. Los tipos numéricos controlan la división y los resultados de agregación, mientras que el redondeo controla cuánta precisión muestras. Conservarás los decimales durante los cálculos, elegirás un tratamiento adecuado para un denominador vacío y redondearás solo la medida final. La misma expresión breve puede comportarse de forma diferente entre bases de datos, por lo que se señala cada diferencia relevante.

4.1 Evita la división entera en promedios y porcentajes

Dividir dos valores enteros puede descartar la fracción antes incluso de mostrar la respuesta. Esto importa cuando construyes una media o un porcentaje a partir de totales y recuentos.

Asegúrate de tener un operando decimal antes de dividir

En SQLite y PostgreSQL, 7 / 2 devuelve 3. Con valores de entrada enteros, SUM(quantity) / COUNT(*) sobre la tabla de pedidos devuelve 2: 19 artículos divididos entre ocho pedidos pierden su parte fraccionaria. En PostgreSQL, SUM de una columna INTEGER devuelve BIGINT, que aquí sigue utilizando división entera.

Escribe 1.0 * SUM(quantity) / COUNT(*) para obtener 2,375 en ambos motores. Multiplicar por 1,0 crea un operando decimal antes de la división. SUM(quantity) / COUNT(*) * 1.0 da 2,0 porque la división ya ha descartado la fracción. Las operaciones con la misma precedencia se evalúan de izquierda a derecha.

Para esta tabla, AVG(quantity) da directamente 2,375 en SQLite y PostgreSQL. La fórmula manual importa cuando necesitas un denominador diferente o un porcentaje.

Calcula un porcentaje

Tres de los ocho pedidos tienen importes de al menos 100. El recuento de esos pedidos dividido entre el recuento de todos los pedidos mide su proporción. Multiplica por 100,0:

SELECT 100.0 * COUNT(CASE WHEN amount >= 100 THEN 1 END) / COUNT(*) AS pct_large FROM orders;

El resultado es 37,5. Utilizar el entero 100 produce en cambio 37 en SQLite y en la división entre recuentos enteros de PostgreSQL. Redondear después solo cambiaría cómo se muestra 37.

Una consulta de toda la tabla puede no tener filas que coincidan. NULLIF(COUNT(*), 0) devuelve NULL cuando el recuento es cero, por lo que 100.0 * COUNT(discount) / NULLIF(COUNT(*), 0) devuelve NULL para un conjunto de entrada vacío. Un denominador cero sin protección produce un error en PostgreSQL; SQLite devuelve NULL. Una proporción NULL puede representar claramente que «no hay pedidos que medir».

Comprueba la base de datos y el tipo de entrada
Base de datosComportamiento que debes tener en cuenta
SQLiteLa división entera trunca; AVG devuelve coma flotante.
PostgreSQLLa división entera trunca; AVG de una entrada entera o NUMERIC devuelve NUMERIC.
SQL ServerLa división entera trunca; AVG de una entrada entera devuelve un entero.
MySQL y Oracle/ conserva el resultado fraccionario para operandos enteros.

En SQL Server, utiliza AVG(quantity * 1.0) o convierte los valores de entrada a DECIMAL antes de calcular el promedio. En PostgreSQL, SUM de una columna BIGINT devuelve NUMERIC, por lo que su división no tiene por qué comportarse como SUM de una columna INTEGER. MySQL devuelve DECIMAL para las sumas de valores de entrada enteros.

Una conversión de tipo también puede crear el operando decimal necesario: utiliza CAST(SUM(quantity) AS REAL) en SQLite o CAST(SUM(quantity) AS NUMERIC) en PostgreSQL. La conversión a NUMERIC de SQLite puede conservar un entero, por lo que esa conversión por sí sola no garantiza una división decimal.

Distingue los decimales exactos de las aproximaciones

Los tipos de coma flotante almacenan aproximaciones binarias. NUMERIC y DECIMAL de PostgreSQL admiten valores decimales exactos; las sumas de coma flotante pueden mostrar pequeñas anomalías como 0,30000000000000004. La afinidad NUMERIC de SQLite no proporciona almacenamiento decimal exacto. Para obtener totales monetarios exactos allí, almacena céntimos como enteros, súmalos y divide entre 100,0 para mostrarlos.

Puntos clave

  • Crea un operando decimal antes de dividir totales o recuentos enteros.
  • Multiplicar después de una división entera no puede recuperar las cifras perdidas.
  • Utiliza NULLIF para gestionar un denominador cero.
  • Los tipos de resultado de las funciones de agregación dependen tanto del motor como del tipo de entrada.
  • La afinidad NUMERIC de SQLite no proporciona almacenamiento decimal exacto.
  • SQL Server necesita valores de entrada decimales para obtener un promedio fraccionario de enteros.

4.2 Redondea los resultados de agregación

El redondeo determina cuántas cifras muestra un resultado. Conserva el cálculo completo hasta el último paso para que las decisiones de presentación no cambien la medida que estás calculando.

Redondea un resultado de agregación

ROUND(x, n) redondea a n cifras después de la coma decimal. ROUND(x) redondea a un número entero. Por ejemplo, ROUND(3.14159, 2) es 3,14.

SELECT region, ROUND(AVG(amount), 2) AS avg_amount FROM orders GROUP BY region; da East 86,67, North 175, West 70 y región NULL 30. SQLite puede mostrar 175,0, mientras que el resultado NUMERIC de PostgreSQL muestra 175,00. Ambos representan el mismo número. Redondear un número y dar formato a una etiqueta de texto de anchura fija son tareas diferentes.

Redondea después de sumar o calcular el promedio

Para tres cargos de 0,44, suma primero para obtener 1,32 y después redondea a un decimal para obtener 1,3. ROUND(SUM(fee), 1) sigue esa secuencia. SUM(ROUND(fee, 1)) redondea cada cargo a 0,4 y después los suma, lo que da 1,2. El redondeo anticipado ha cambiado el total.

Del mismo modo, ROUND(100 * 1 / 3, 1) da 33,0 en SQLite y PostgreSQL porque la división entera ya ha producido 33. ROUND(100.0 * 1 / 3, 1) conserva la fracción y da 33,3. Elige el tipo de cálculo antes de redondear.

Los porcentajes redondeados pueden no sumar 100 %. Tres partes iguales pueden mostrarse como 33,3 % cada una y sumar 99,9 %. Las proporciones originales siguen cubriendo el total. Recalcular una parte arbitraria para forzar el total mostrado cambia el significado de esa cifra.

Utiliza un tipo de entrada compatible

PostgreSQL admite ROUND(value, n) con dos argumentos para NUMERIC. Si temp es DOUBLE PRECISION, escribe ROUND(CAST(AVG(temp) AS NUMERIC), 2). El promedio de 20,5; 21,25 y 19,0 es 20,25, y la conversión te permite utilizar el redondeo con dos argumentos. Con amount de tipo entero, el promedio de PostgreSQL ya es NUMERIC, por lo que no hace falta convertirlo.

Para valores NUMERIC exactos de PostgreSQL, los casos situados justo a mitad se redondean alejándose de cero: 2,5 se convierte en 3 y -2,5 se convierte en -3. SQLite también da 3,0 y -3,0 para estos ejemplos. El redondeo de coma flotante de PostgreSQL depende de la plataforma; es habitual redondear al número par más cercano. La aproximación binaria también puede situar un decimal justo por debajo del punto medio previsto. No utilices un empate concreto de coma flotante como regla general para la aritmética decimal exacta.

Observa otras dos diferencias entre dialectos

PostgreSQL, MySQL, SQL Server y Oracle utilizan un número negativo de posiciones decimales para redondear a la izquierda de la coma decimal. ROUND(1234.5, -2) da 1200. SQLite trata un segundo argumento negativo como cero y da 1235,0. Para redondear a centenas en SQLite, utiliza ROUND(x / 100.0) * 100.

La conversión a entero también depende de la base de datos: SQLite elimina la parte fraccionaria, por lo que 2,9 se convierte en 2; PostgreSQL lo redondea a 3. Utiliza ROUND cuando quieras redondear. En cambio, TRUNC(x, n) de PostgreSQL elimina cifras: TRUNC(2.97, 1) es 2,9, mientras que redondearlo a un decimal da 3,0.

Puntos clave

  • Redondea el resultado de agregación después de completar su cálculo.
  • El redondeo no puede corregir una división entera anterior.
  • Los porcentajes redondeados pueden sumar 99,9 % o 100,1 %.
  • Convierte un promedio de coma flotante de PostgreSQL a NUMERIC para utilizar ROUND con dos argumentos.
  • Las posiciones negativas de redondeo y las conversiones a entero difieren entre bases de datos.
5

Responde preguntas de negocio con consultas de resumen

Los informes de negocio suelen necesitar varias medidas de la misma población: todos los pedidos, los pedidos grandes y la proporción de pedidos grandes. La agregación condicional mantiene esas medidas una al lado de la otra. Después construirás un informe completo a partir de su pregunta, comprobarás totales y categorías ausentes, y utilizarás un segundo paso de agregación cuando la pregunta trate sobre clientes u otros grupos en lugar de pedidos individuales.

5.1 Cuenta y suma según una condición con CASE

La agregación condicional permite que distintas medidas utilicen distintas aportaciones manteniendo el mismo conjunto global de filas. Una expresión CASE decide qué aporta cada fila a un recuento o una suma.

Cuenta las filas que cumplen la condición

COUNT(CASE WHEN amount >= 100 THEN 1 END) cuenta los pedidos de al menos 100. La expresión devuelve 1 cuando se cumple la condición y NULL para las demás filas porque no tiene ELSE. COUNT omite esos valores NULL, por lo que quedan tres coincidencias en la tabla de pedidos.

SUM(CASE WHEN amount >= 100 THEN 1 ELSE 0 END) cuenta las coincidencias sumando unos y ceros. Cuando existen filas de entrada, da el mismo recuento. COUNT(CASE WHEN amount >= 100 THEN 1 ELSE 0 END) no lo hace: ni 1 ni 0 son NULL, por lo que cuenta los ocho pedidos.

Suma los importes que cumplen la condición

Para obtener un total condicional, devuelve el propio importe:

SELECT region, COUNT(*) AS orders, COUNT(CASE WHEN amount >= 100 THEN 1 END) AS large_orders, SUM(CASE WHEN amount >= 100 THEN amount ELSE 0 END) AS large_total FROM orders GROUP BY region;

East tiene tres pedidos, un pedido grande y un total de pedidos grandes de 120. North tiene dos pedidos, ambos grandes, que suman 350. West tiene dos pedidos, ningún pedido grande y un total de pedidos grandes de cero. El grupo de región NULL tiene un pedido y ceros en ambas medidas de pedidos grandes.

La salida conserva West porque sus filas de entrada siguen existiendo. Añadir WHERE amount >= 100 eliminaría las filas de West antes de agrupar, por lo que West desaparecería. Ese filtro también haría que COUNT(*) contara solo los pedidos grandes, perdiendo la comparación con todos los pedidos.

Utiliza el denominador correcto

Dentro de cada región, calcula el porcentaje de pedidos grandes con ROUND(100.0 * COUNT(CASE WHEN amount >= 100 THEN 1 END) / COUNT(*), 1) AS pct_large. East da 33,3; North 100,0; West 0,0 y el grupo NULL 0,0. Cada denominador es el recuento de pedidos de ese grupo, no el recuento de ocho de toda la tabla.

Para un informe sin agrupar que pueda no tener filas, protege el denominador con NULLIF(COUNT(*), 0). Un recuento sobre un conjunto de entrada vacío es cero, pero un porcentaje de una población vacía no tiene denominador.

Crea varias columnas de categoría

Un único resultado puede mostrar un recuento por región:

SELECT COUNT(CASE WHEN region = 'East' THEN 1 END) AS east, COUNT(CASE WHEN region = 'West' THEN 1 END) AS west, COUNT(CASE WHEN region = 'North' THEN 1 END) AS north FROM orders;

Los recuentos son tres, dos y dos. El pedido de Eli no cumple ninguna de estas condiciones de región con nombre. Añade COUNT(CASE WHEN region IS NULL THEN 1 END) para contar el único pedido sin región. Comparar una región NULL con un nombre no produce una condición verdadera.

Reconoce sintaxis alternativas

PostgreSQL y SQLite desde la versión 3.30.0 admiten COUNT(*) FILTER (WHERE amount >= 100). El filtro se aplica a esa función de agregación, por lo que un COUNT(*) contiguo sin filtro sigue contando todos los pedidos. MySQL y SQL Server no admiten esta sintaxis FILTER de agregación; la forma con CASE funciona en ambos.

SQLite y MySQL también permiten SUM(amount >= 100) porque las comparaciones producen valores de verdad numéricos. PostgreSQL rechaza SUM de valores booleanos. Utiliza la forma con CASE cuando una consulta deba funcionar en todos estos motores.

Puntos clave

  • Coloca condiciones dentro de las funciones de agregación para mantener juntas las medidas de distintos subconjuntos.
  • COUNT(CASE ... THEN 1 END) omite las filas que no cumplen la condición.
  • ELSE 0 funciona para una suma condicional, pero hace que un recuento condicional también cuente las filas que no cumplen la condición.
  • Un porcentaje dentro de un grupo utiliza la población de ese grupo como denominador.
  • Un FILTER de agregación cambia solo los valores de entrada de esa función de agregación.
  • Utiliza IS NULL para contar por separado las categorías ausentes.

5.2 Construye y comprueba una consulta de resumen a partir de una pregunta

Una consulta de resumen empieza con una pregunta sobre una población con un nivel de detalle concreto. Traduce esas decisiones antes de escribir SQL y después comprueba que la salida siga respondiendo la pregunta original.

Construye el informe en orden

Plantea: «Para cada mes de 2026 con al menos tres pedidos, ¿cuántos pedidos se hicieron y cuál fue el importe medio, con dos decimales?».

  1. Las medidas son COUNT(*) y AVG(amount).
  2. La granularidad, o significado de una fila de resultado, es un mes del calendario.
  3. La condición de fila conserva las fechas de 2026.
  4. La condición de grupo exige al menos tres pedidos.
  5. La salida debe ordenarse por mes, con el promedio redondeado para mostrarlo.

En SQLite:

SELECT strftime('%Y-%m', order_date) AS month, COUNT(*) AS orders, ROUND(AVG(amount), 2) AS avg_amount FROM orders WHERE order_date >= '2026-01-01' AND order_date < '2027-01-01' GROUP BY strftime('%Y-%m', order_date) HAVING COUNT(*) >= 3 ORDER BY month;

Para valores de fecha de PostgreSQL, sustituye la expresión de mes en ambos lugares por to_char(order_date, 'YYYY-MM'). El intervalo de fechas incluye el inicio de 2026 y excluye el inicio de 2027.

Enero tiene dos pedidos y no cumple la condición de grupo. Febrero tiene tres pedidos que suman 305, con un promedio de 101,67. Marzo tiene tres que suman 275, con un promedio de 91,67. Los grupos que permanecen representan seis pedidos, no ocho, porque HAVING ha eliminado enero.

Comprueba antes de eliminar grupos con el filtro

Ejecuta primero el informe sin HAVING. Los recuentos de todos los grupos deben sumar el recuento de filas bajo el mismo filtro WHERE, y los totales deben sumar el total sin agrupar. Aquí esas comprobaciones dan ocho y 780. No compares los totales de los grupos conservados con todo el conjunto de entrada después de excluir algunos grupos.

Busca un grupo NULL, examina el orden de los resultados y vuelve a calcular un grupo filtrando la tabla original. Para East, WHERE region = 'East' debe dar tres pedidos que sumen 260. Una discrepancia puede revelar una columna de agrupación adicional, un filtro de filas mal colocado o una expresión que se haya convertido en NULL.

Distingue el promedio por pedido del promedio por cliente

AVG(amount) es 97,5 por pedido. El gasto medio por cliente pide una unidad diferente: los cinco totales de cliente son 165, 140, 350, 95 y 30. Su promedio es 156.

Calcúlalo en dos etapas:

SELECT AVG(total) AS avg_customer_total FROM (SELECT customer, SUM(amount) AS total FROM orders GROUP BY customer) AS per_customer;

La consulta interna crea una fila por cliente. La consulta externa calcula el promedio de esas filas, de modo que cada cliente aporta una vez. Si todos los clientes están identificados, 1.0 * SUM(amount) / COUNT(DISTINCT customer) da el mismo 156. Cuando los números de pedidos son desiguales, calcular el promedio de los importes de pedido es un cálculo diferente.

Resume los propios grupos

Para contar los clientes con más de un pedido, primero enuméralos y después cuenta sus filas:

SELECT COUNT(*) FROM (SELECT customer FROM orders GROUP BY customer HAVING COUNT(*) > 1) AS repeat_customers;

La respuesta es tres. Anidar directamente funciones de agregación, como en MAX(AVG(amount)) en un mismo nivel de consulta, falla en SQLite y PostgreSQL. Para encontrar la región con el promedio más alto, ordena los promedios agrupados: ORDER BY AVG(amount) DESC LIMIT 1 devuelve North con 175. Oracle también admite funciones de grupo anidadas, pero un nivel de consulta separado hace explícitos los dos cálculos. Comprueba los empates cuando un informe pida un resultado máximo.

Puntos clave

  • Elige las medidas, la granularidad, las condiciones de fila y las condiciones de grupo a partir de la pregunta.
  • Comprueba los recuentos y totales de los grupos antes de eliminar grupos con HAVING.
  • Un promedio por cliente necesita los totales de cliente como valores de entrada.
  • Utiliza una consulta interna agrupada y una función de agregación externa para resumir grupos.

Ejemplos de Agregación y agrupación en SQL

5 Lecciones Interactivas

1

Convierte filas de pedidos en cifras de resumen fiables

13 pasos
Elige funciones de agregación y recuentos, y después sigue los efectos de los valores ausentes.
  1. 1
    IntroducciónLee la pregunta del informe

    Una persona responsable quiere un total de pedidos, un recuento de clientes y un descuento medio. Cada uno parece una cifra sencilla, pero utiliza los datos de entrada de forma diferente. Cada uno es un agregado, que convierte muchas filas en un único valor, y una elección equivocada da una cifra engañosa. Construiremos esas medidas a partir de los ocho pedidos: primero combinaremos los importes, después elegiremos qué contar y, por último, decidiremos cómo cambia NULL el promedio. Sigue preguntándote qué aporta una fila de entrada al resultado.

  2. 2
    ExplicaciónCombina los importes

    Una función de agregación combina valores de muchas filas en un resumen. SUM(amount) suma los importes, AVG(amount) calcula su media y MIN(amount) y MAX(amount) localizan los extremos. Sin GROUP BY, todos los pedidos que cumplen las condiciones forman un grupo. Puedes seleccionar varias funciones de agregación juntas porque cada una describe ese mismo grupo de filas de entrada.

  3. 3
    EjemploCalcula un resumen completo

    Los importes de los pedidos son 120, 80, 45, 200, 60, 95, 150 y 30. Suman 780. Dividir ese total entre ocho da un promedio de 97,5; el mínimo es 30 y el máximo es 200.

    SELECT SUM(amount) AS total, AVG(amount) AS mean_amount, MIN(amount) AS low, MAX(amount) AS high FROM orders;

    La salida es una fila con cuatro medidas etiquetadas.

  4. 4
    EjemploElige los datos de entrada antes de sumar

    Ahora pregunta solo por East. WHERE region = 'East' conserva los importes 120, 45 y 95 antes de que se ejecute la función de agregación.

    SELECT SUM(amount) AS total FROM orders WHERE region = 'East';

    La salida es 260. Las otras regiones no aportan nada porque sus pedidos no cumplen la condición de fila. Un filtro sobre las filas de entrada cambia el propio total, no solo la etiqueta que muestra.

  5. 5
    DesafíoMantén cada cantidad con su precio

    Una tabla de ventas tiene dos filas: cantidad 4 a un precio unitario de 6 y cantidad 2 a un precio unitario de 9. ¿Qué devuelve SUM(quantity * unit_price) y por qué es diferente multiplicar las dos sumas?

    ---reveal---

    Los ingresos de las filas son 24 y 18, por lo que la suma es 42. Multiplicar las sumas da seis por 15, es decir, 90, porque ya no empareja cada cantidad con el precio de su propia fila.

  6. 6
    ExplicaciónCuenta registros o clientes

    Los pedidos indican Ana, Ben, Ana, Chen, Ben, Dara, Chen y Eli. COUNT(customer) cuenta ocho nombres registrados, incluidas las apariciones repetidas. COUNT(DISTINCT customer) cuenta cinco nombres diferentes.

    La redacción determina cuál corresponde: un recuento de pedidos necesita filas, mientras que un recuento de clientes necesita clientes distintos. Los nombres iguales en pedidos separados son repeticiones esperadas, no clientes adicionales.

  7. 7
    EjemploCuenta la categoría ausente

    La columna region tiene ocho filas, pero solo siete valores registrados. COUNT(*) es ocho, COUNT(region) es siete y COUNT(DISTINCT region) es tres.

    Restar el recuento de valores registrados del recuento de filas da una región ausente. Observa que una lista de regiones distintas también incluiría una fila NULL; el recuento de valores distintos ignora ese NULL en lugar de tratarlo como una cuarta región con nombre.

  8. 8
    DesafíoElige el recuento correcto

    Una columna coupon contiene NULL, 0, 8, 8 y 0. ¿Qué valores devuelven COUNT(*), COUNT(coupon) y COUNT(DISTINCT coupon), en ese orden?

    ---reveal---

    Devuelven cinco, cuatro y dos. Hay cinco filas, cuatro valores registrados y dos valores registrados diferentes, 0 y 8. Los ceros registrados cuentan; NULL no entra en ninguno de los dos recuentos de columna.

  9. 9
    ExplicaciónExcluye una calificación desconocida

    Considera las calificaciones 80, NULL, 70 y 90. Las calificaciones registradas suman 240. AVG(score) divide entre las tres calificaciones registradas y devuelve 80.

    No divide entre las cuatro filas: una calificación ausente no es un cero conocido. Si el valor ausente representa un examen al que no se presentó y que debe calificarse con cero, el cálculo previsto cambia a AVG(COALESCE(score, 0)), que da 60.

  10. 10
    EjemploColoca el valor predeterminado en la etapa correcta

    Falta el descuento en cuatro pedidos. En SUM(amount - discount), cada una de esas expresiones de fila se convierte en NULL, por lo que solo contribuyen las otras cuatro. Sus importes netos suman 345.

    Si un valor ausente significa que no hay descuento, utiliza SUM(amount - COALESCE(discount, 0)). Así contribuyen los ocho pedidos y el total es 750. COALESCE alrededor de la suma ya calculada no puede recuperar las aportaciones de las filas omitidas.

  11. 11
    DesafíoGestiona un grupo sin valores conocidos

    Una consulta conserva tres filas cuyos importes son todos NULL. ¿Qué devuelven COUNT(*), COUNT(amount) y SUM(amount)?

    ---reveal---

    Devuelven tres, cero y NULL. Existen filas, pero no hay importes registrados que contar o sumar. Un conjunto de entrada vacío también daría una suma NULL, pero su recuento de filas sería cero. Utiliza COALESCE(SUM(amount), 0) solo cuando el informe deba mostrar ese total ausente como cero.

  12. 12
    DesafíoComprueba un cálculo y su población

    Cuatro registros de servicio tienen cargos de 20, 30, 40 y 50, con abonos de 2, NULL, 0 y NULL. Un abono ausente significa que no hay abono. ¿Qué cargo neto total y qué recuento de abonos registrados debe mostrar el informe?

    ---reveal---

    Utiliza SUM(charge - COALESCE(credit, 0)) para obtener un total neto de 138, y COUNT(credit) para obtener dos abonos registrados. El abono de cero cuenta como registrado; sustituir NULL dentro de la suma conserva los cuatro cargos.

  13. 13
    RepasoMantén la medida vinculada a sus datos de entrada

    Elige la función de agregación a partir de la pregunta y después sigue los valores que entran en ella. Los recuentos distinguen filas, valores registrados y valores diferentes. Para los promedios y la aritmética de filas, comprueba qué elimina NULL y si una sustitución tiene un significado real. Cuando una respuesta resulte sorprendente, examina las filas que permanecen y sus aportaciones antes de cambiar el SQL.

2

Construye un informe con el nivel de detalle adecuado

14 pasos
Agrupa por categorías, corrige columnas ambiguas y crea grupos combinados o calculados.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónDecide qué representa una fila del resultado
  2. 2
    ExplicaciónReúne filas por región
  3. 3
    EjemploMantén visible el grupo NULL
  4. 4
    ConsejoOrdena antes de conservar las primeras filas
  5. 5
    DesafíoPredice cuántos grupos quedan
  6. 6
    ExplicaciónExplica por qué un nombre es ambiguo
  7. 7
    EjemploCorrige el informe a partir de su pregunta
  8. 8
    ConsejoReconoce un resultado permisivo
  9. 9
    DesafíoElige una corrección con sentido
  10. 10
    EjemploDivide un grupo por un segundo valor
  11. 11
    ExplicaciónCrea una etiqueta de mes del calendario
  12. 12
    DesafíoEncuentra la expresión de agrupación
  13. 13
    DesafíoComprueba la granularidad y las etiquetas del informe
  14. 14
    RepasoInterpreta cada fila como un grupo
3

Coloca filtros antes o después de la agregación

10 pasos
Sigue WHERE y HAVING a lo largo de un informe y predice cómo cambia la respuesta según su ubicación.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónDistingue la población de la selección
  2. 2
    ExplicaciónComprueba el grupo ya calculado
  3. 3
    EjemploUtiliza un recuento sin mostrarlo
  4. 4
    DesafíoComprueba el valor real que se compara
  5. 5
    ExplicaciónSigue las etapas lógicas del resultado
  6. 6
    EjemploElimina primero los pedidos pequeños
  7. 7
    EjemploDespués elimina los totales de grupo pequeños
  8. 8
    DesafíoDiagnostica una pregunta que ha cambiado
  9. 9
    DesafíoCombina restricciones de fila y de grupo
  10. 10
    RepasoDeja que la condición indique su etapa
4

Conserva las fracciones y redondea el resultado final

11 pasos
Sigue los tipos numéricos, evita los denominadores cero y redondea los resultados de agregación en la etapa correcta.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónSepara el cálculo de la presentación
  2. 2
    EjemploEncuentra dónde desaparece la fracción
  3. 3
    ExplicaciónIntroduce el decimal al principio
  4. 4
    ConsejoProtege un denominador vacío
  5. 5
    DesafíoCorrige una expresión de porcentaje
  6. 6
    ExplicaciónRedondea el promedio ya calculado
  7. 7
    EjemploObserva cómo el redondeo anticipado cambia un total
  8. 8
    DesafíoComprueba una diferencia entre dialectos
  9. 9
    ConexiónElige el tipo para importes exactos
  10. 10
    DesafíoComprueba el tipo antes de redondear
  11. 11
    RepasoSigue el número por cada etapa
5

Construye y comprueba un resumen de negocio

13 pasos
Crea medidas de subconjuntos, elige la granularidad del informe y resume resultados agrupados en dos niveles de consulta.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónMantén juntos todos los pedidos y los pedidos seleccionados
  2. 2
    ExplicaciónHaz que las filas que no cumplen la condición aporten NULL
  3. 3
    EjemploMantén disponible el grupo completo
  4. 4
    EjemploSuma el importe o suma uno
  5. 5
    DesafíoConserva el denominador de un subconjunto
  6. 6
    ExplicaciónTraduce la redacción de negocio
  7. 7
    EjemploConstruye el resultado mensual
  8. 8
    ConsejoComprueba antes de ocultar grupos
  9. 9
    ExplicaciónCambia la unidad de entrada de un promedio
  10. 10
    EjemploLee los dos niveles de consulta
  11. 11
    DesafíoElige la unidad correcta para el promedio
  12. 12
    DesafíoCuenta solo los grupos de clientes que cumplen las condiciones
  13. 13
    RepasoComprueba la población y la granularidad

Ejercicios de Agregación y agrupación en SQL

40 Preguntas de Práctica en 4 sets

Set 1: Elige la población y el detalle del informe10 Preguntas de Práctica

Pregunta 1 de 10

Una tabla de incidencias tiene valores de prioridad 0, NULL, 2, 2 y NULL. ¿Qué devuelve COUNT(priority)?
  1. 5
  2. 3
  3. 2
  4. 1
Mostrar respuestaOcultar respuesta
Respuesta: B
COUNT(priority) cuenta los tres valores registrados: cero y las dos apariciones de 2. El cero es un valor conocido, por lo que cuenta. Contar cinco utilizaría el recuento de filas, mientras que contar dos eliminaría las repeticiones además de NULL.

Pregunta 2 de 10

Una tabla work_log tiene las columnas consultant, year y hours. Un informe necesita un total de horas por consultor para 2025 y conservar solo los totales superiores a 120. ¿Qué estructura de consulta responde la petición?
  1. WHERE year = 2025 AND hours > 120 GROUP BY consultant
  2. GROUP BY consultant, hours HAVING SUM(hours) > 120
  3. WHERE hours > 120 GROUP BY consultant, year
  4. WHERE year = 2025 GROUP BY consultant HAVING SUM(hours) > 120
Mostrar respuestaOcultar respuesta
Respuesta: D
La comprobación del año elige los registros de entrada, consultant define una fila de salida y HAVING comprueba cada total de horas ya calculado. Filtrar registros individuales con hours > 120 descartaría aportaciones menores aunque pertenecieran a un consultor cuyo total conjunto supera 120.

Pregunta 3 de 10

Una tabla almacena fechas de entrega como texto ISO: «2025-12-28», «2026-01-04» y «2025-02-19». ¿Qué devuelven MIN(delivery_date) y MAX(delivery_date), en ese orden?
  1. 2025-02-19 y 2026-01-04
  2. 2025-12-28 y 2026-01-04
  3. 2026-01-04 y 2025-02-19
  4. 2026-01-04 y 2025-12-28
Mostrar respuestaOcultar respuesta
Respuesta: A
El texto ISO uniforme de año-mes-día se ordena cronológicamente, por lo que el 19 de febrero de 2025 es la fecha más temprana y el 4 de enero de 2026 es la más tardía. Comparar solo el mes colocaría enero primero, pero MIN y MAX comparan todo el valor de fecha almacenado, empezando por el año.

Pregunta 4 de 10

Una tabla de SQLite tiene pares (city, agent): (A, Jo), (A, Jo), (A, Kai), (NULL, Lee) y (NULL, Lee). ¿Qué devuelve SELECT COUNT(*) FROM (SELECT DISTINCT city, agent FROM visits) AS pairs?
  1. 2
  2. 4
  3. 3
  4. 5
Mostrar respuestaOcultar respuesta
Respuesta: C
El resultado interno tiene tres pares distintos: A/Jo, A/Kai y NULL/Lee. El COUNT(*) externo cuenta las tres filas resultantes, incluido el par que contiene NULL. Devolver dos omitiría ese par como si se hubiera utilizado un recuento de valores de columna que no son NULL en lugar de un recuento de filas.

Pregunta 5 de 10

Cuatro reparaciones tienen valores (cost, credit) de (50, 5), (80, NULL), (40, 0) y (30, NULL). NULL significa que no hay abono. ¿Cuáles son SUM(cost - credit) y el coste neto total previsto, en ese orden?
  1. 195 y 195
  2. 85 y 85
  3. 115 y 195
  4. 85 y 195
Mostrar respuestaOcultar respuesta
Respuesta: D
Sin sustitución, las expresiones con abono NULL se convierten en NULL, por lo que solo quedan 45 y 40, que suman 85. Sustituir los abonos ausentes por cero dentro de la expresión incluye las cuatro reparaciones y da 195. Un COALESCE externo deja sin cambios la suma 85, que no es NULL, y no puede recuperar las reparaciones omitidas.

Pregunta 6 de 10

Los totales de cliente son Ali 90, Bea 120, Cam 120 y Dev 75. ¿Qué filas conserva ORDER BY total DESC, customer ASC LIMIT 2, suponiendo que los nombres se ordenan alfabéticamente?
  1. Ali 90 y Bea 120
  2. Bea 120 y Cam 120
  3. Cam 120 y Bea 120
  4. Bea 120 y Ali 90
Mostrar respuestaOcultar respuesta
Respuesta: B
El total descendente coloca primero ambos totales de 120, y el nombre de cliente ascendente sitúa Bea antes de Cam. Después, LIMIT conserva esas dos filas. Invertir su orden ignora la segunda clave de ordenación explícita, que resuelve el empate aunque ambos clientes tengan la misma medida.

Pregunta 7 de 10

Una tabla de cargos contiene tres valores de 0,36. ¿Qué producen ROUND(SUM(fee), 1) y SUM(ROUND(fee, 1)), en ese orden, si se ignoran las pequeñas anomalías de presentación de coma flotante?
  1. 1,2 y 1,1
  2. 1,1 y 1,1
  3. 1,1 y 1,2
  4. 1,2 y 1,2
Mostrar respuestaOcultar respuesta
Respuesta: C
El total exacto es 1,08, que se redondea a 1,1 con un decimal. Redondear primero cada cargo da tres valores de 0,4, que suman 1,2. Tratar ambas expresiones como equivalentes supone que redondear cada aportación no puede cambiar el resultado de agregación, pero aquí esos cambios en los valores de entrada se acumulan.

Pregunta 8 de 10

Una tabla contiene pares (site, worker): (A, Ren), (A, Ren), (A, Sol), (B, Ren), (NULL, Sol) y (NULL, Sol). ¿Cuántos grupos resultan al agrupar por site y, después, por site y worker?
  1. 3 y 4
  2. 3 y 6
  3. 2 y 3
  4. 3 y 3
Mostrar respuestaOcultar respuesta
Respuesta: A
Agrupar por site da A, B y un grupo NULL. Añadir worker divide A en Ren y Sol, mientras que B y el grupo NULL siguen teniendo un valor de trabajador cada uno, lo que da cuatro grupos. Contar seis trataría las filas de entrada repetidas como grupos separados aunque sus valores de agrupación coincidan.

Pregunta 9 de 10

Un registro de formación tiene los valores Seguridad, Seguridad, Herramientas, Herramientas, Herramientas y Primeros auxilios. ¿Qué devuelve SELECT training FROM roster GROUP BY training HAVING COUNT(*) >= 3?
  1. Seguridad y Herramientas
  2. Herramientas
  3. Herramientas y Primeros auxilios
  4. Ninguna fila
Mostrar respuestaOcultar respuesta
Respuesta: B
Solo Herramientas tiene al menos tres registros, por lo que la consulta devuelve ese nombre de formación. Seguridad tiene dos y no alcanza el umbral inclusivo. El recuento puede decidir qué grupos cumplen la condición sin mostrarse en SELECT; aun así, se calcula para cada grupo que utiliza HAVING.

Pregunta 10 de 10

El equipo A tiene importes de 20, 80 y 100; el equipo B tiene 60 y 90. Después de WHERE amount >= 60 GROUP BY team HAVING AVG(amount) > 80, ¿qué queda?
  1. B con un promedio de 75.
  2. A con un promedio aproximado de 66,67.
  3. A con un promedio de 90.
  4. A con 90 y B con 75.
Mostrar respuestaOcultar respuesta
Respuesta: C
WHERE elimina el importe de 20 de A, por lo que A queda con un promedio de 90 y B con un promedio de 75. HAVING conserva solo A porque su nuevo promedio supera 80. Utilizar el promedio original de A, aproximadamente 66,67, pasa por alto el filtro de filas anterior y comprueba la población equivocada.
Set 2: Interpreta recuentos, grupos y cálculos10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

Una tabla de entregas registra distancias de 14, 22 y 35. ¿Qué valor devuelve SUM(distance)?
  1. 35
  2. 23.67
  3. 71
  4. 3
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

Cinco solicitudes tienen valores de estado closed, open, closed, open y open. ¿Qué devuelve COUNT(CASE WHEN status = 'closed' THEN 1 ELSE 0 END)?
  1. 5
  2. 2
  3. 3
  4. 0
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Cuatro entregas tienen retrasos de 6, NULL, 10 y 8 minutos. Un retraso ausente significa que no se ha medido. ¿Qué promedio devuelve AVG(delay)?
  1. 6
  2. 24
  3. 10
  4. 8
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Una tabla shifts contiene los valores de departamento Ventas, Soporte, Ventas, NULL y NULL. ¿Cuántas filas devuelve SELECT department, COUNT(*) FROM shifts GROUP BY department?
  1. 5
  2. 3
  3. 2
  4. 4
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Una tabla parts tiene varios proveedores por categoría. El informe necesita una fila por categoría y el número de proveedores diferentes. ¿Qué lista SELECT corresponde a FROM parts GROUP BY category?
  1. category, supplier, COUNT(*)
  2. category, COUNT(DISTINCT supplier)
  3. category, COUNT(supplier)
  4. category, MIN(supplier)
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

Una tabla de pagos de PostgreSQL tiene una columna DATE paid_on con registros de 2024 a 2026. ¿Qué expresión de agrupación mantiene separado cada mes del calendario?
  1. EXTRACT(MONTH FROM paid_on)
  2. EXTRACT(YEAR FROM paid_on)
  3. paid_on
  4. to_char(paid_on, 'YYYY-MM')
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Un informe agrupado tiene los totales de equipo Rojo 180, Azul 260 y Verde 200. ¿Qué equipos permanecen después de HAVING SUM(amount) > 200?
  1. Azul
  2. Azul y Verde
  3. Rojo y Azul
  4. Verde
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Una consulta de PostgreSQL selecciona categoría y coste total, agrupa solo por categoría y utiliza ORDER BY supplier. Las categorías tienen varios proveedores. ¿Cómo puede mostrar primero las categorías de mayor coste sin cambiar su granularidad?
  1. Añade supplier a GROUP BY.
  2. Utiliza ORDER BY supplier DESC.
  3. Utiliza ORDER BY SUM(cost) DESC.
  4. Añade supplier a la lista SELECT.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

En SQLite, unas cantidades enteras suman 23 en seis filas. ¿Qué devuelve SUM(quantity) / COUNT(*) * 1.0?
  1. 3.0
  2. 3.8333333333333335
  3. 4.0
  4. 23.0
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Una tabla de SQLite tiene tres cargos de 0,26. Una consulta selecciona ROUND(SUM(fee), 1), pero conserva el grupo global solo con HAVING SUM(fee) >= 0.8. ¿Qué resultado devuelve?
  1. Una fila que contiene 0,8.
  2. Una fila que contiene 0,9.
  3. Una fila que contiene NULL.
  4. Ninguna fila.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Set 3: Combina valores ausentes, tipos y grupos10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

¿Qué devuelve SELECT 17 / 5 en SQLite?
  1. 3.4
  2. 4
  3. 0
  4. 3
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

Una consulta agrupa solicitudes de reembolso por equipo, pero selecciona un nombre de empleado sin agregar. Cada equipo tiene varios empleados. SQLite muestra un nombre y PostgreSQL rechaza la consulta. ¿Qué explica la diferencia?
  1. SQLite agrupa por empleado automáticamente; PostgreSQL necesita una agrupación explícita.
  2. SQLite permite una columna sin agrupar ni agregar; el nombre no describe todo el equipo.
  3. SQLite devuelve el primer empleado alfabéticamente; PostgreSQL necesita una ordenación explícita.
  4. SQLite elimina los empleados adicionales antes de agrupar; PostgreSQL conserva a todos.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

La sede L tiene importes de 30, 50 y 80; la sede M tiene 20 y 40. Necesitas el porcentaje de pedidos de al menos 60 de cada sede, incluidas las sedes sin ninguno. ¿Qué porcentajes deben aparecer?
  1. L 100,0 %; M ausente.
  2. L 20,0 %; M 0,0 %.
  3. L 33,3 %; M 0,0 %.
  4. L 50,0 %; M 0,0 %.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

La clienta Inez tiene importes de 20, 30 y 50; Omar tiene 200. ¿Cuáles son el importe medio por pedido y el importe total medio por cliente, en ese orden?
  1. 75 y 150
  2. 150 y 75
  3. 75 y 100
  4. 100 y 150
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Una tabla stock tiene filas (department, quantity, price): (A, 2, 7), (A, 3, 4) y (B, 5, 9). ¿Qué devuelve SELECT SUM(quantity * price) FROM stock WHERE department = 'A'?
  1. 55
  2. 71
  3. 26
  4. 14
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

Una columna region contiene NULL, West, West, East y NULL. ¿Qué devuelve COUNT(DISTINCT region)?
  1. 2
  2. 3
  3. 5
  4. 1
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Ninguna fila de jobs cumple state = 'queued'. ¿Qué devuelve SELECT team, COALESCE(SUM(hours), 0) FROM jobs WHERE state = 'queued' GROUP BY team?
  1. Una fila de equipo NULL con cero.
  2. Una fila de equipo NULL con NULL.
  3. Una fila de total cero por equipo.
  4. Ninguna fila.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Una tabla tiene valores de área North, NULL, South, NULL y North. Después de WHERE area IS NOT NULL GROUP BY area, ¿cuáles son los recuentos de los grupos?
  1. North 2; South 1; NULL 2.
  2. North 2; South 1.
  3. North 1; South 1.
  4. North 3; South 2.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Un informe necesita los importes medios de factura por oficina, incluyendo solo facturas de 2025 y mostrando solo oficinas con más de cinco facturas que cumplan esa condición. ¿Dónde corresponden la comprobación de fecha y la de recuento?
  1. Ambas comprobaciones en WHERE.
  2. Fecha en HAVING; recuento en WHERE.
  3. Ambas comprobaciones en HAVING.
  4. Fecha en WHERE; recuento en HAVING.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Los pedidos tienen valores (fecha, importe): (2025-01-10, 90), (2026-01-12, 140), (2026-01-20, 60) y (2026-02-03, 110). Agrupa por año y mes y por CASE WHEN amount >= 100 THEN 'large' ELSE 'small' END. ¿Cuántos grupos resultan?
  1. 4
  2. 3
  3. 2
  4. 5
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Set 4: Diagnostica y completa informes10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

Un informe agrupa una tabla de reservas por habitación. ¿Qué condición HAVING conserva las habitaciones con al menos cuatro reservas?
  1. HAVING COUNT(*) >= 4
  2. HAVING COUNT(*) > 4
  3. HAVING COUNT(*) = 4
  4. HAVING COUNT(*) <= 4
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

La sucursal A tiene importes de 10, 40 y 70; la sucursal B tiene 30 y 50. Compara agrupar después de WHERE amount >= 30 con agrupar todas las filas y utilizar HAVING MIN(amount) >= 30. ¿Qué promedios aparecen?
  1. WHERE: A 40 y B 40; HAVING: solo B 40.
  2. WHERE: A 55 y B 40; HAVING: A 55 y B 40.
  3. WHERE: A 55 y B 40; HAVING: solo B 40.
  4. WHERE: solo B 40; HAVING: A 40 y B 40.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Un informe sin agrupar puede no tener filas de entrada. ¿Qué expresión da el porcentaje de filas con un valor registrado, conserva los decimales y devuelve NULL para una población vacía tanto en SQLite como en PostgreSQL?
  1. 100 * COUNT(value) / NULLIF(COUNT(*), 0)
  2. 100.0 * COUNT(value) / NULLIF(COUNT(*), 0)
  3. 100.0 * COUNT(value) / COALESCE(COUNT(*), 1)
  4. 100.0 * COUNT(*) / NULLIF(COUNT(value), 0)
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

En PostgreSQL, temperature es DOUBLE PRECISION. ¿Cómo redondeas su promedio a dos decimales?
  1. ROUND(AVG(temperature), 2)
  2. CAST(ROUND(AVG(temperature)) AS NUMERIC)
  3. ROUND(CAST(AVG(temperature) AS INTEGER), 2)
  4. ROUND(CAST(AVG(temperature) AS NUMERIC), 2)
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

En PostgreSQL, COUNT(*) FILTER (WHERE paid = 1) aparece junto a COUNT(*) en una consulta agrupada sin cláusula WHERE. ¿Qué restringe el filtro?
  1. Todas las funciones de agregación del grupo.
  2. Solo la presentación del resultado final.
  3. Solo la función de recuento de pagados.
  4. Todas las filas antes de formar grupos.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

El cliente U tiene importes de 40 y 70, V tiene 60, 60 y 10, y W tiene 150. ¿Cuántos clientes tienen al menos dos pedidos y un total superior a 120?
  1. 2
  2. 3
  3. 5
  4. 1
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Una consulta conserva cuatro filas con los valores NULL, NULL, NULL y NULL. ¿Cuáles son COUNT(*), COUNT(value) y MAX(value), en ese orden?
  1. 4, 0, NULL
  2. 0, 0, NULL
  3. 4, 4, NULL
  4. 4, 0, 0
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Una tabla visits tiene pares (customer, zone): (Jo, East), (Jo, East), (Kai, West), (Kai, North), (Lee, NULL) y (Lee, NULL). ¿Cómo cambia el número de grupos al añadir zone a la agrupación por customer?
  1. Se mantiene en tres.
  2. Aumenta de tres a cuatro.
  3. Aumenta de tres a seis.
  4. Aumenta de tres a cinco.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Un informe agrupado incluye las zonas East, West y NULL. Un filtro de filas es WHERE zone <> 'West'. ¿Qué grupos de zona pueden permanecer?
  1. East y NULL.
  2. East y West.
  3. Solo East.
  4. Solo NULL.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

En una tabla de pedidos de SQLite, mayo de 2025 tiene importes de 20 y 100, mayo de 2026 tiene 50 y 70, y junio de 2026 tiene 200. Un informe debe mostrar solo meses de 2026 con al menos dos pedidos y su importe medio redondeado. ¿Qué resultado corresponde a la petición?
  1. 2026-05: cuatro pedidos, promedio 60,00.
  2. 2026-05: dos pedidos, promedio 60,00.
  3. 2026-06: un pedido, promedio 200,00.
  4. 2026-05: dos pedidos, promedio 120,00.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

¿Te atascas con una pregunta tuya? Ayuda con Tareas

Términos Clave

58 Términos Clave, cada uno con su definición

A

Agregación condicional
La agregación condicional hace que la aportación de cada fila dependa de una condición y permite obtener varias medidas de subconjuntos en un informe.
Un informe regional puede mostrar juntos todos los pedidos y los pedidos grandes sin filtrar primero los pedidos pequeños.
Agrupación por varias columnas
La agrupación por varias columnas forma un grupo por cada combinación de valores de agrupación presente en las filas de entrada que permanecen.
Agrupar por región y cliente da resultados separados de East para Ana y Dara, manteniendo juntos los pedidos de Ana.
Alias de SELECT
Un alias de SELECT es un nombre de salida asignado a una expresión, que puede utilizarse en ORDER BY, pero cuyos usos en otros lugares dependen del dialecto.
PostgreSQL acepta ORDER BY total, pero necesita que se escriba la expresión de agregación completa en un HAVING del mismo nivel.
AVG
AVG es una función de agregación que calcula la media aritmética de sus valores de entrada que no son NULL, utilizando cada valor registrado una vez.
AVG(amount) da 97,5 para ocho pedidos cuyos importes suman 780, y mide el importe medio por pedido.

C

CAST
CAST convierte un valor al tipo SQL solicitado, con efectos que dependen del tipo de destino y del motor de base de datos.
Una conversión a REAL en SQLite permite la división decimal, mientras que una conversión a NUMERIC puede mantener como entero un valor sin parte fraccionaria.
Categoría definida con CASE
Una categoría definida con CASE es una etiqueta asignada por condiciones de una expresión CASE, que puede convertirse en la base de un informe agrupado.
Un umbral de amount >= 100 coloca un pedido de exactamente 100 en la categoría etiquetada como «large».
Clave de año y mes
Una clave de año y mes identifica un mes del calendario junto con su año y evita que se reúna el mismo mes de años diferentes.
Las etiquetas «2025-01» y «2026-01» producen grupos separados en un informe mensual que abarca ambos años.
COALESCE
COALESCE es una función que devuelve el primer argumento que no es NULL y permite elegir un valor predeterminado para una entrada o un resultado final.
COALESCE(SUM(amount), 0) muestra cero cuando un conjunto de entrada vacío produciría un total NULL.
Columna de agrupación
Una columna de agrupación proporciona los valores que determinan qué filas de entrada pertenecen al mismo grupo en una consulta de resumen agrupada.
Elegir el cliente como columna de agrupación hace que el informe trate sobre clientes en lugar de pedidos individuales.
Columna sin agrupar ni agregar
Una columna sin agrupar ni agregar es una columna seleccionada que no es una columna de agrupación ni está dentro de una función de agregación en una consulta de agregación.
SQLite puede mostrar un cliente junto al total de una región aunque varios clientes hayan contribuido a esa región.
Combinación distinta
Una combinación distinta es un conjunto único de valores de las columnas seleccionadas, tratado como una fila en un resultado sin duplicados.
East/Ana y East/Dara son pares separados cuando un informe enumera combinaciones distintas de región y cliente.
Comparación sin redondeo
Una comparación sin redondeo comprueba el valor calculado original, aunque la salida seleccionada muestre una versión redondeada.
Un promedio mostrado como 86,67 puede no cumplir HAVING AVG(amount) >= 86.67 si su valor exacto es menor.
Conciliación de resultados
La conciliación de resultados comprueba que los recuentos y totales de los grupos sumen las medidas equivalentes sin agrupar sobre la misma población filtrada.
Ejecuta primero sin HAVING para que los grupos excluidos no expliquen una diferencia entre el informe y el total de entrada.
Condición de fila
Una condición de fila puede evaluarse para un registro de entrada, como si su fecha está en un intervalo o su importe alcanza un umbral.
La comprobación amount >= 60 puede conservar un pedido de East y eliminar otro antes de que exista ningún resumen regional.
Condición de grupo
Una condición de grupo comprueba una propiedad de un grupo ya calculado, como si su recuento o promedio alcanza un umbral requerido.
Un mínimo de tres pedidos por mes es una condición de grupo porque necesita el recuento mensual ya calculado.
Conjunto de entrada con todos los valores NULL
Un conjunto de entrada con todos los valores NULL tiene filas, pero no valores registrados para la expresión que se agrega, por lo que COUNT(x) es cero.
Cuatro pedidos con descuentos desconocidos dan COUNT(*) cuatro y COUNT(discount) cero cuando un filtro selecciona solo esos pedidos.
Conjunto de entrada vacío
Un conjunto de entrada vacío es un conjunto sin filas que entren en un cálculo, como cuando una condición WHERE no encuentra registros que coincidan.
Un recuento sin agrupar de pedidos de South devuelve cero cuando todos los pedidos de la tabla pertenecen a otras regiones.
COUNT(*)
COUNT(*) es la forma de agregación que cuenta todas las filas de entrada, incluidas las que tienen valores ausentes en una o más columnas.
Una tabla con ocho pedidos tiene un COUNT(*) igual a ocho aunque un pedido no tenga una región registrada.
COUNT(column)
COUNT(column) cuenta las filas con un valor que no es NULL en la columna indicada; incluye valores repetidos y ceros registrados.
COUNT(discount) incluye un pedido con descuento cero, pero excluye uno con descuento NULL.
COUNT(DISTINCT column)
COUNT(DISTINCT column) cuenta los valores diferentes de una columna que no son NULL, contando solo una vez los valores registrados repetidos.
Utiliza COUNT(DISTINCT customer) para obtener el número de clientes identificados, aunque algunos hagan varios pedidos.
Criterio de desempate
Un criterio de desempate es una clave de ordenación adicional que da a las filas un orden reproducible cuando sus valores de ordenación anteriores son iguales.
ORDER BY total DESC, customer da a los totales de cliente empatados un orden estable antes de aplicar un límite.

D

Dependencia funcional
Una dependencia funcional significa que un valor determina otro, como una clave primaria de pedido que determina el cliente de ese pedido.
PostgreSQL puede seleccionar el cliente cuando la agrupación incluye la clave primaria de la tabla de pedidos.
Detección de duplicados
La detección de duplicados encuentra valores repetidos agrupando los registros por esos valores y conservando los grupos con recuentos superiores a uno.
Agrupar por cliente y utilizar HAVING COUNT(*) > 1 identifica a los clientes que aparecen en varios registros de pedido.
Diferencia por redondeo
Una diferencia por redondeo es una diferencia causada por reducir la precisión, como cuando las partes redondeadas ya no suman el total redondeado.
Tres proporciones porcentuales iguales mostradas con un decimal suman 99,9 %, aunque las proporciones exactas cubren el 100 %.
DISTINCT
DISTINCT elimina valores o filas duplicados en la etapa en la que se aplica, como dentro de una función de agregación o en la lista de salida.
SUM(DISTINCT quantity) suma cada valor de cantidad una vez, por lo que puede excluir del total ventas reales con cantidades repetidas.
División entera
La división entera divide operandos enteros y descarta la parte fraccionaria en SQLite, PostgreSQL y SQL Server.
En SQLite, dividir 19 artículos entre ocho pedidos con operandos enteros da 2 en lugar de la media 2,375.

E

Expresión de agregación
Una expresión de agregación aplica una función de resumen a una columna o a un cálculo por fila, como sumar la cantidad multiplicada por el precio de cada fila.
SUM(amount - discount) evalúa la resta en cada fila antes de sumar los resultados que no son NULL.
Expresión de agrupación
Una expresión de agrupación calcula un valor de agrupación a partir de cada fila, como un mes del calendario o una categoría asignada mediante CASE.
Una expresión de año y mes combina los pedidos de febrero y los mantiene separados de los de febrero de otro año.

F

FILTER de una función de agregación
Un FILTER de una función de agregación restringe sus valores de entrada y deja que otras funciones de agregación de la misma consulta utilicen otras filas.
PostgreSQL puede colocar un recuento filtrado de pedidos grandes junto a un recuento sin filtrar de todos los pedidos del mismo grupo.
Función de agregación
Una función de agregación combina valores de varias filas de entrada en un resultado, como un recuento, una suma, un promedio o un extremo.
Un informe de ventas utiliza SUM(amount) para convertir muchos importes de pedido en un total para el periodo seleccionado.

G

Granularidad
La granularidad de un informe es lo que representa una fila de salida, como un cliente o un mes, y determina la agrupación necesaria.
Un informe con una fila por cliente necesita medidas a nivel de cliente aunque la tabla de origen registre pedidos.
GROUP BY
GROUP BY es la cláusula que reúne las filas de entrada por valores compartidos de columnas o expresiones para que las funciones de agregación se ejecuten una vez por grupo.
GROUP BY region permite que una misma consulta calcule un recuento de pedidos y un total de importes separados para cada región.
Grupo de valores NULL
Un grupo de valores NULL contiene las filas cuyo valor de agrupación está ausente; SQL reúne esas filas en un grupo de resultado.
Varios pedidos sin región comparten un total que puede mostrarse con una etiqueta como «Sin región».

H

HAVING
HAVING es la cláusula que filtra grupos utilizando sus valores de agrupación o sus resultados de agregación después de calcularlos.
HAVING SUM(amount) > 200 conserva las regiones según su total, sin eliminar pedidos pequeños de los grupos que permanecen.

I

Intercalación
Una intercalación es un conjunto de reglas que utiliza la base de datos para comparar y ordenar texto, incluido cómo afectan las mayúsculas y minúsculas a las comparaciones.
El mínimo de unos valores de texto puede cambiar con la intercalación aunque las filas y la consulta MIN sigan siendo las mismas.
IS NULL
IS NULL es una comprobación de SQL que es verdadera cuando falta un valor y permite seleccionar o contar explícitamente los registros con valores ausentes.
WHERE region IS NULL selecciona los pedidos cuya región no se ha registrado, como el pedido de un cliente llamado Eli.

M

Medida
Una medida es la cantidad que calcula un informe, como un recuento, un total o un promedio, con el nivel de detalle elegido para el informe.
Un informe mensual de pedidos puede utilizar el recuento de pedidos y el importe medio como dos medidas de la misma población mensual.
MIN y MAX
MIN y MAX son funciones de agregación que encuentran los valores de entrada mínimo y máximo que no son NULL según las reglas de comparación de la base de datos.
MIN(order_date) encuentra la fecha más temprana cuando la columna contiene fechas o texto de fecha ISO con un formato uniforme.

N

NULL
NULL indica un valor SQL ausente o desconocido; las operaciones aritméticas con él producen NULL, y es diferente de cero o de una cadena vacía.
Un descuento desconocido puede hacer que amount - discount sea NULL, lo que provoca que SUM omita el valor calculado de esa fila.
NULLIF
NULLIF devuelve NULL cuando sus dos argumentos son iguales y, en caso contrario, devuelve el primero, lo que resulta útil para los divisores cero.
NULLIF(COUNT(*), 0) convierte en NULL el denominador de un informe vacío y evita un error de división entre cero en PostgreSQL.
NUMERIC y DECIMAL
NUMERIC y DECIMAL proporcionan tipos decimales exactos en PostgreSQL; en SQLite, estos nombres dan afinidad sin almacenamiento decimal exacto.
Para obtener totales monetarios exactos en SQLite, los céntimos expresados como enteros evitan depender de valores fraccionarios almacenados como aproximaciones binarias.
Número de coma flotante
Un número de coma flotante almacena una aproximación binaria de muchos valores decimales, por lo que algunos cálculos pueden mostrar pequeñas anomalías de redondeo.
Una suma con DOUBLE PRECISION de PostgreSQL puede mostrar 0,30000000000000004 donde la aritmética decimal exacta da 0,3.

O

ONLY_FULL_GROUP_BY
ONLY_FULL_GROUP_BY es un modo de MySQL que rechaza las expresiones de consultas agrupadas con valores sin agrupar que la agrupación no determina.
MySQL normalmente rechaza seleccionar un cliente arbitrario cuando la consulta agrupa los pedidos solo por región.
Operando decimal
Un operando decimal es un valor numérico de entrada que permite conservar un resultado fraccionario cuando se introduce antes de una división que sería entera.
Multiplicar la suma por 1,0 antes de dividir conserva la parte fraccionaria de un promedio construido a partir de totales.
Orden lógico de procesamiento de consultas
El orden lógico de procesamiento de consultas describe las etapas que definen el resultado de una consulta, incluido el filtrado de filas antes de los cálculos de grupo.
Seguir WHERE antes de GROUP BY explica por qué eliminar pedidos pequeños cambia el promedio posterior de una región.
ORDER BY
ORDER BY es la cláusula que solicita un orden de salida definido, incluida la ordenación de filas agrupadas por una función de agregación o su alias.
ORDER BY total DESC enumera primero los totales de grupo más altos después de calcular cada grupo.

P

Porcentaje dentro del grupo
Un porcentaje dentro del grupo mide un subconjunto como proporción de su propio grupo, utilizando la población completa de ese grupo como denominador.
Un pedido grande entre tres pedidos de East representa aproximadamente el 33,3 % de los pedidos de East, independientemente de los recuentos de otras regiones.
Promedio por cliente
Un promedio por cliente hace que el total de cada cliente contribuya una vez, lo que difiere de calcular el promedio de todos los importes de pedido individuales.
Cuando cinco clientes hacen ocho pedidos que suman 780, su promedio por cliente es 156 aunque el promedio de los ocho pedidos sea 97,5.

R

Recuento condicional
Un recuento condicional cuenta solo las filas que cumplen una condición elegida, a menudo haciendo que las demás devuelvan NULL dentro de COUNT.
COUNT(CASE WHEN amount >= 100 THEN 1 END) cuenta los pedidos grandes y omite los resultados NULL de las filas que no cumplen la condición.
Redondeo final
El redondeo final reduce la precisión después del cálculo completo de agregación y evita los cambios acumulados al redondear primero cada valor de entrada.
Tres cargos de 0,44 suman 1,32 antes de redondearse a 1,3; redondear primero cada cargo produciría un total de 1,2.
Regla de agrupación
La regla de agrupación exige que cada valor seleccionado tenga un significado definido para su grupo mediante la agrupación o la agregación.
Una región con varios clientes no puede proporcionar un único nombre de cliente sin agregar salvo que la consulta especifique cómo elegirlo.
ROUND
ROUND es una función que redondea un valor numérico; su segundo argumento normalmente especifica las cifras después de la coma decimal.
ROUND(AVG(amount), 2) redondea el promedio ya calculado a dos decimales y mantiene intacto el cálculo anterior.

S

SUM
SUM es una función de agregación que suma los valores numéricos que no son NULL de una columna o expresión a lo largo de sus filas de entrada.
SUM(quantity * unit_price) suma los ingresos de las filas después de multiplicar cada cantidad por su precio correspondiente.

T

Tabla derivada
Una tabla derivada es el resultado de una consulta utilizado en FROM, que permite que una segunda consulta resuma las filas creadas por la primera.
Una consulta interna crea totales de cliente; una consulta externa trata esos totales como sus valores de entrada al calcular su promedio.
Total condicional
Un total condicional suma los importes de las filas que cumplen una condición, normalmente con una expresión CASE que devuelve cero para las demás.
Un total de pedidos grandes devuelve desde CASE el propio importe que cumple la condición; devolver 1 contaría pedidos en su lugar.
Truncamiento
El truncamiento elimina cifras fraccionarias sin redondear; PostgreSQL ofrece TRUNC y SQLite lo aplica al convertir a entero.
TRUNC(2.97, 1) da 2,9 en PostgreSQL, mientras que ROUND(2.97, 1) da 3,0 para ese decimal exacto.

V

Valor exactamente a mitad entre dos resultados de redondeo
Un valor exactamente a mitad entre dos resultados de redondeo está a la misma distancia de dos resultados posibles; el resultado elegido depende del tipo numérico y de la regla de redondeo.
El redondeo exacto de NUMERIC en PostgreSQL lleva 2,5 a 3 y -2,5 a -3, alejando de cero ambos empates.

W

WHERE
WHERE es la cláusula que filtra filas de entrada individuales antes de agrupar y determina qué registros contribuyen a los resúmenes posteriores.
Un informe restringido a pedidos de 2026 utiliza una condición de fecha en WHERE antes de calcular los totales mensuales.

Sobre esta unidad

Por StudeliInformar de un error

Crea tus propios Materiales de Estudio

Convierte tus notas, diapositivas y documentos en Guías de Estudio, Preguntas de Práctica, Flashcards y 6 herramientas más.

Comenzar