27th Jul 2023 Lectura de 16 minutos Como Usar SUM() con OVER(PARTITION BY) en SQL Martyna Sławińska SQL PARTITION BY funciones de ventana Índice La Cláusula OVER() en SQL Ejemplo 1A: Cálculo de la suma de cada grupo - SUM() con OVER(PARTITION BY ...) Ejemplo 1B: Calcular el salario de cada puesto de trabajo Ejemplo 2: Calcular la Relación entre el Valor de una Fila y el Total Ejemplo 2: Calcular la Relación entre el Valor de una Fila y el Total ¿Cuál es la diferencia entre SUM() con OVER(PARTITION BY …) y utilizar SUM() con GROUP BY? Ejemplo 3: Cálculo de un total acumulado mediante SUM() con OVER(PARTITION BY) Ejemplo 4: Recuento de objetos en categorías personalizadas Ejemplo 5: Cálculo del total de un pedido con descuentos utilizando SUM() con CASE WHEN Siga adelante y SUM() con OVER() y PARTITION BY Descubra casos reales de uso de la función SUM() con la cláusula OVER(PARTITION BY). Aprenda la sintaxis y vea 5 ejemplos diferentes. Utilizamos las funciones de ventana de SQL para realizar operaciones en grupos de datos. Estas operaciones incluyen las funciones matemáticas SUM(), COUNT(), AVG(), y más. En este artículo, explicaremos qué hace SUM() con OVER(PARTITION BY) en SQL. Le mostraremos los casos de uso más comunes en aplicaciones del mundo real para determinar la relación entre el valor de la fila individual y el valor total, calcular totales corridos y encontrar un total de pedido personalizado que incluya descuentos para ciertos productos. Para obtener una guía detallada sobre el uso de SUM() con OVER() y otras funciones de ventana, siga nuestro curso interactivo Funciones de ventana interactivo. Explica en detalle todos los conceptos de las funciones de ventana de SQL y contiene más de 200 ejercicios. Comencemos. La Cláusula OVER() en SQL En SQL, la cláusula OVER() se utiliza para introducir funciones ventana. La sintaxis general es SELECT … <window function> OVER(...) … OVER() indica a la base de datos que queremos utilizar funciones ventana. La función ventana puede ser una función agregada, como SUM(), u otra función ventana. Una función de ventana trabaja sobre un "marco de ventana", o un conjunto de filas relacionadas con la fila actual. OVER() define el marco de ventana para cada fila. Una cláusula OVER() vacía indica a la base de datos que todo el conjunto de resultados es el marco de ventana. Veamos un ejemplo de la sintaxis de SUM() OVER(). Utilizaremos la tabla employees de los datos de ejemplo proporcionados por Oracle Live SQL. Esta tabla consta de las siguientes columnas emp_id es el identificador del empleado. name es el nombre del empleado. job es el título del puesto. dept_id es el identificador del departamento. salary es el salario del empleado. EMP_IDNAMEJOBDEPT_IDSALARY 7839KINGPRESIDENT105000 7698BLAKEMANAGER302850 … 7900JAMESCLERK30950 7934MILLERCLERK101300 Podemos utilizar la función SUM() con la cláusula OVER() para obtener el salario total de todos los empleados y mostrar el salario total junto al salario de cada empleado. SELECT emp_id, name, job, dept_id, salary, SUM(salary) OVER() AS total_salary FROM employees; emp_idNAMEJOBDEPT_IDSALARYTOTAL_SALARY 7839KINGPRESIDENT10500029025 7698BLAKEMANAGER30285029025 … 7900JAMESCLERK3095029025 7934MILLERCLERK10130029025 La función SUM() se ejecuta para cada fila de la tabla. Cada vez que se llama, obtiene la información salarial de todas las filas de la tabla para calcular el importe total del salario. El salario total se muestra junto a los detalles de cada fila individual. Los detalles de las filas individuales se conservan y se muestran junto al salario total. En este ejemplo, el marco de la ventana (el conjunto de filas sobre el que opera SUM() ) es todo el conjunto de datos. Puede añadir cláusulas adicionales en OVER() para cambiar el marco de la ventana. Ejemplo 1A: Cálculo de la suma de cada grupo - SUM() con OVER(PARTITION BY ...) La cláusula OVER() puede contener detalles sobre la forma en que queremos particionar los datos. Utilizamos la cláusula PARTITION BY en OVER() para dividir los datos en particiones, o grupos. El uso de PARTITION BY es similar al uso de GROUP BY en que las filas se dividen en grupos basados en el valor de algunas columnas. Cuando usamos SUM() OVER(PARTITION BY …), podemos calcular la suma de valores para cada grupo, o partición, de datos. Por ejemplo, podemos calcular el salario total de cada departamento: SELECT emp_id, name, job, dept_id, salary, SUM(salary) OVER(PARTITION BY dept_id) AS dept_total_salary FROM employees; Este es el resultado: EMP_IDNAMEJOBDEPT_IDSALARYDEPT_TOTAL_SALARY 7782CLARKMANAGER1024508750 7934MILLERCLERK1013008750 7839KINGPRESIDENT1050008750 7902FORDANALYST20300010875 7788SCOTTANALYST20300010875 7566JONESMANAGER20297510875 7369SMITHCLERK2080010875 7876ADAMSCLERK20110010875 7521WARDSALESMAN3012509400 7654MARTINSALESMAN3012509400 7844TURNERSALESMAN3015009400 7900JAMESCLERK309509400 7499ALLENSALESMAN3016009400 7698BLAKEMANAGER3028509400 Utilizamos SUM(salary) OVER(PARTITION BY dept_id) para obtener el salario total por departamento. La cláusula PARTITION BY divide las filas en grupos en función de la columna dept_id. Las filas con dept_id igual a 10 se colocan en un grupo (marcado en amarillo en la tabla anterior), las filas con dept_id igual a 20 se colocan en otro grupo (marcado en verde) y, por último, las filas con dept_id igual a 30 se colocan en otro grupo (marcado en rojo). La función SUM() calcula la suma de las filas de cada grupo. Tenga en cuenta que cuando se utiliza SUM() OVER(PARTITION BY), se conservan los detalles de las filas individuales. Puede, por ejemplo, ver los detalles del empleado llamado Ford: su puesto, su salario y cómo se compara con el total de salarios de su departamento. Este es el uso más típico de SUM() OVER(PARTITION BY): se calcula el valor de la suma para cada grupo de datos y se mantienen los detalles de las filas individuales. Veamos un ejemplo similar. Ejemplo 1B: Calcular el salario de cada puesto de trabajo Podemos utilizar SUM(salary) OVER(PARTITION BY job) para obtener el salario total por puesto de trabajo. Veámoslo: SELECT emp_id, name, job, dept_id, salary, SUM(salary) OVER(PARTITION BY job) AS job_total_salary FROM employees; Este es el resultado: EMP_IDNAMEJOBDEPT_IDSALARYJOB_TOTAL_SALARY 7782CLARKMANAGER1024508275 7698BLAKEMANAGER3028508275 7566JONESMANAGER2029758275 7934MILLERCLERK1013004150 7369SMITHCLERK208004150 7876ADAMSCLERK2011004150 7900JAMESCLERK309504150 7902FORDANALYST2030006000 7788SCOTTANALYST2030006000 7521WARDSALESMAN3012505600 7654MARTINSALESMAN3012505600 7844TURNERSALESMAN3015005600 7499ALLENSALESMAN3016005600 7839KINGPRESIDENT1050005000 Esta vez, las filas se agrupan en función del valor del puesto en lugar del ID del departamento. Los empleados con el mismo puesto de trabajo se ponen en un grupo y calculamos el salario total de las personas en este puesto. La función SUM() se aplica a todos los salarios de cada grupo: el salario total del grupo "Manager" es la suma de 2450, 2850 y 2975, que son los salarios de los tres managers que hay en nuestra tabla. Ejemplo 2: Calcular la Relación entre el Valor de una Fila y el Total Típicamente, queremos ver la comparación entre cada fila individual y la suma total. Calculemos el porcentaje de cada salario individual del total de salarios de su departamento. SELECT emp_id, name, job, dept_id, salary, ROUND(100.0 * salary / SUM(salary) OVER(PARTITION BY dept_id), 2) AS percentage_of_dept_total_salary FROM employees; EMP_IDNAMEJOBDEPT_IDSALARYPERCENTAGE_OF_DEPT_TOTAL_SALARY 7782CLARKMANAGER10245028 7934MILLERCLERK10130014.86 7839KINGPRESIDENT10500057.14 7902FORDANALYST20300027.59 7788SCOTTANALYST20300027.59 7566JONESMANAGER20297527.36 7369SMITHCLERK208007.36 7876ADAMSCLERK20110010.11 7521WARDSALESMAN30125013.3 7654MARTINSALESMAN30125013.3 7844TURNERSALESMAN30150015.96 7900JAMESCLERK3095010.11 7499ALLENSALESMAN30160017.02 7698BLAKEMANAGER30285030.32 Esta vez, las filas se agrupan en función del valor job en lugar del ID del departamento. Los empleados con el mismo puesto de trabajo se colocan en un grupo y calculamos el salario total de las personas en este puesto. La función SUM() se aplica a todos los salarios de cada grupo: el salario total del grupo "Manager" es la suma de 2450, 2850 y 2975, que son los salarios de los tres managers que hay en nuestra tabla. Ejemplo 2: Calcular la Relación entre el Valor de una Fila y el Total Típicamente, queremos ver la comparación entre cada fila individual y la suma total. Calculemos el porcentaje de cada salario individual con respecto a los salarios totales de su departamento. SELECT emp_id, name, job, dept_id, salary, ROUND(100.0 * salary / SUM(salary) OVER(PARTITION BY dept_id), 2) AS percentage_of_dept_total_salary FROM employees; EMP_IDNAMEJOBDEPT_IDSALARYPERCENTAGE_OF_DEPT_TOTAL_SALARY 7782CLARKMANAGER10245028 7934MILLERCLERK10130014.86 7839KINGPRESIDENT10500057.14 7902FORDANALYST20300027.59 7788SCOTTANALYST20300027.59 7566JONESMANAGER20297527.36 7369SMITHCLERK208007.36 7876ADAMSCLERK20110010.11 7521WARDSALESMAN30125013.3 7654MARTINSALESMAN30125013.3 7844TURNERSALESMAN30150015.96 7900JAMESCLERK3095010.11 7499ALLENSALESMAN30160017.02 7698BLAKEMANAGER30285030.32 Podemos ver, por ejemplo, que el analista llamado Scott tiene un salario individual de 3000; esto supone el 27,59% del total de salarios de su departamento. A continuación se desglosan las funciones utilizadas para realizar esta tarea: Tomamos cada salario individual y lo dividimos por el salario total del departamento: salary / SUM(salary) OVER(PARTITION BY dept_id) Para obtener un porcentaje, lo multiplicamos por 100%: 0 * salary / SUM(salary) OVER(PARTITION BY dept_id) A continuación, utilizamos la función ROUND() para obtener dos dígitos decimales: ROUND(100.0 * salary / SUM(salary) OVER(PARTITION BY dept_id), 2) Calcular la relación entre la fila individual y la suma de un grupo es otro caso de uso muy común de SUM() con OVER(PARTITION BY). De forma similar, puedes calcular la diferencia entre el total del grupo y la fila individual. ¿Cuál es la diferencia entre SUM() con OVER(PARTITION BY …) y utilizar SUM() con GROUP BY? La cláusula PARTITION BY realiza una tarea similar a la cláusula GROUP BY. Tanto OVER(PARTITION BY) como GROUP BY dividen el conjunto de datos en particiones o grupos. Al utilizar la función SUM(), ambas expresiones calculan la suma de cada grupo. Entonces, ¿cuál debe elegir? Cuando se utiliza GROUP BY, los detalles de las filas individuales se contraen. Eche un vistazo: SELECT job, SUM(salary) AS total_salary FROM employees GROUP BY job; JOBTOTAL_SALARY ANALYST6000 CLERK4150 SALESMAN5600 MANAGER8275 PRESIDENT5000 En este caso, obtenemos el valor salarial total de cada puesto sin tener en cuenta los salarios individuales de los empleados. Sin embargo, si desea comparar el valor de la suma total con los valores de las filas individuales (por ejemplo, para calcular la relación entre el valor individual y el total), la forma de hacerlo es OVER(PARTITION BY …). Devuelve todas las filas individuales junto con el valor de la suma total de cada fila. Este valor de la suma total puede variar en función de la partición a la que pertenezca la fila. SELECT name, job, salary, SUM(salary) OVER(PARTITION BY job) AS total_salary FROM employees; NAMEJOBSALARYTOTAL_SALARY FORDANALYST30006000 SCOTTANALYST30006000 SMITHCLERK8004150 JAMESCLERK9504150 ADAMSCLERK11004150 MILLERCLERK13004150 BLAKEMANAGER28508275 JONESMANAGER29758275 CLARKMANAGER24508275 KINGPRESIDENT50005000 TURNERSALESMAN15005600 ALLENSALESMAN16005600 WARDSALESMAN12505600 MARTINSALESMAN12505600 El valor total_salary coincide con los resultados de la consulta anterior con GROUP BY. Pero aquí también se pueden ver los salarios individuales. Por ejemplo, hay dos analistas que ganan 6000 en total; cada uno de ellos gana 3000. La regla general es: Si sólo desea conocer el valor de la suma de cada grupo y no le interesan los detalles de cada fila individual, debe utilizar la cláusula GROUP BY. Si está interesado tanto en la suma de cada grupo como en los detalles de las filas individuales, debe utilizar SUM() OVER(PARTITION BY). Ejemplo 3: Cálculo de un total acumulado mediante SUM() con OVER(PARTITION BY) Otro uso común de la sintaxis SUM() OVER(...) es calcular el total acumulado. Un total acumulado es la suma acumulada de los números anteriores de una columna. Los totales móviles se utilizan para calcular valores que se acumulan a lo largo del tiempo. Por ejemplo, con un total acumulado puedes calcular el uso mensual de datos móviles sumando el valor de cada día posterior a la suma de los valores de los días anteriores. Del mismo modo, puedes calcular cómo aumenta cada día el número de usuarios registrados o cómo aumentan los ingresos totales con cada transacción. Utilizamos la sintaxis SUM() con OVER(PARTITION BY … ORDER BY …) para calcular el total actual. Veamos un ejemplo. Utilizaremos la orders tabla de datos de ejemplo proporcionada por Oracle Live SQL. Esta tabla almacena datos históricos de pedidos. Cada pedido tiene su fecha (order_date), representante de ventas (sales_rep_id), y valor total (order_total). Aquí calculamos el valor total actual para cada representante de ventas: SELECT order_date, sales_rep_id, order_total, SUM(order_total) OVER(PARTITION BY sales_rep_id ORDER BY order_date) AS running_total FROM orders; ORDER_DATESALES_REP_IDORDER_TOTALRUNNING_TOTAL 29-MAR-07 02.22.40.536996 PM15310794.610794.6 16-AUG-07 03.34.12.234359 PM15378279.689074.2 04-OCT-07 09.53.34.362632 PM15312989203.2 21-NOV-07 10.22.33.263332 AM15313824103027.2 16-DEC-07 08.19.55.462332 PM15311188.5114215.7 27-JUL-06 12.22.59.662632 PM15452471.952471.9 27-JUL-06 01.34.16.562632 PM154364656117.9 29-JUN-07 09.53.41.984501 AM1544856165.9 01-JUL-07 04.49.13.615512 PM15422056385.9 02-JUL-07 03.34.44.665170 AM15460056985.9 01-SEP-07 09.53.26.934626 AM154545162436.9 02-OCT-07 05.49.34.678340 PM1546653.469090.3 10-NOV-07 03.49.25.526321 AM15450125119215.3 19-NOV-07 02.41.54.696211 PM15442283.2161498.5 17-DEC-07 05.03.52.562632 PM15410474.6171973.1 Para ello, dividimos nuestra tabla por representante de ventas y, a continuación, ordenamos cada partición por fecha: SUM(order_total) OVER(PARTITION BY sales_rep_id ORDER BY order_date) El nuevo elemento sintáctico es ORDER BY. Define cómo se ordenan las filas en cada marco de ventana. La función SUM() se aplica a cada fila; suma el valor actual de order_total con el valor anterior de running_total; los totales se calculan por separado para cada partición (aquí, para cada ID de representante de ventas). Echemos un vistazo más de cerca al representante de ventas con un ID de 153. Su primer pedido fue el29 de marzo y tuvo un valor total de 10794,6. En este momento, el total acumulado (la suma) es igual al valor del pedido. Su segundo pedido fue el 16de agosto por 78279,6; ahora el total acumulado es igual a la suma de los valores de su primer y segundo pedido (10794,6 + 78279,6 = 89074,2). Después del tercer pedido, el total acumulado es igual al total acumulado anterior más el valor del tercer pedido (89074,2 + 129 = 89203,2). Este proceso es similar para el representante de ventas con el ID 154. El cálculo de un total acumulado es un patrón común cuando se utiliza SQL para el análisis de datos. Puede leer cómo calcular un total en SQL en otra sección de nuestro blog. Ejemplo 4: Recuento de objetos en categorías personalizadas La función SUM() se utiliza a menudo con la sentencia CASE WHEN para contar objetos en categorías personalizadas. Por ejemplo, es posible que desee calcular el salario total de los empleados en puestos directivos de un departamento y mostrarlo junto a los detalles de cada empleado. Puede lograrlo utilizando SUM() OVER(PARTITION BY) en combinación con CASE WHEN. Revisemos primero la sentencia CASE WHEN. Es similar a la sentencia if común a muchos lenguajes de programación. Se utiliza para definir el valor de una expresión en diferentes situaciones o casos. En el siguiente ejemplo, utilizamos la sentencia CASE WHEN para identificar a cada empleado como directivo (gerentes y presidentes) o como empleado normal (todos los demás puestos de trabajo). Eche un vistazo: SELECT emp_id, name, job, dept_id, CASE WHEN job IN (‘PRESIDENT’, ‘MANAGER’) THEN ‘MANAGEMENT’ ELSE ‘REGULAR’ END AS emp_type salary FROM employees; La sentencia CASE evalúa todas las condiciones de WHEN. Si encuentra la condición coincidente, devuelve el valor en la rama THEN. Si no encuentra la condición coincidente, devuelve el valor dado después de ELSE. En nuestro ejemplo, los empleados en el puesto de presidente o gerente se etiquetan como 'Management'. A todos los demás puestos de trabajo se les asigna la etiqueta 'Regular'. Este es el resultado de la consulta: EMP_IDNAMEJOBDEPT_IDEMP_TYPESALARY 7782CLARKMANAGER10MANAGEMENT2450 7934MILLERCLERK10REGULAR1300 7839KINGPRESIDENT10MANAGEMENT5000 7902FORDANALYST20REGULAR3000 7788SCOTTANALYST20REGULAR3000 7566JONESMANAGER20MANAGEMENT2975 7369SMITHCLERK20REGULAR800 7876ADAMSCLERK20REGULAR1100 7521WARDSALESMAN30REGULAR1250 7654MARTINSALESMAN30REGULAR1250 7844TURNERSALESMAN30REGULAR1500 7900JAMESCLERK30REGULAR950 7499ALLENSALESMAN30REGULAR1600 7698BLAKEMANAGER30MANAGEMENT2850 Puede obtener más información sobre CASE en nuestro artículo Cómo utilizar CASE en SQL. También puede utilizar la sentencia CASE con SUM() para sumar valores en categorías personalizadas. Esta es la consulta: SELECT dept_id, SUM( CASE WHEN job IN (‘PRESIDENT’, ‘MANAGER’) THEN salary ELSE 0 END) AS dept_management_salary, SUM( CASE WHEN job IN (‘PRESIDENT’, ‘MANAGER’) THEN 0 ELSE salary END) AS dept_regular_salary FROM employees GROUP BY dept_id; DEPT_IDDEPT_MANAGEMENT_SALARYDEPT_REGULAR_SALARY 1074501300 2029757900 3028506550 Para los empleados en puestos directivos, la primera sentencia CASE devuelve el valor de la columna salary. A continuación, la función SUM() en combinación con GROUP BY suma todos los salarios de los empleados en puestos directivos con la misma dept_id. De este modo, se calcula el salario total de los directivos por departamento. La segunda sentencia CASE calcula el salario total por departamento para todos los empleados fijos. Puede calcular el salario total de los empleados en posición directiva de un departamento y mostrarlo junto a los detalles del empleado utilizando SUM() con PARTITION BY: SELECT emp_id, name, job, dept_id, CASE WHEN job IN (‘PRESIDENT’, ‘MANAGER’) THEN ‘MANAGEMENT’ ELSE ‘REGULAR’ END AS emp_type salary, SUM( CASE WHEN job IN (‘PRESIDENT’, ‘MANAGER’) THEN salary ELSE 0 END) OVER(PARTITION BY dept_id) AS dept_management_salary FROM employees; EMP_IDNAMEJOBDEPT_IDEMP_TYPESALARYDEPT_MANAGEMENT_SALARY 7782CLARKMANAGER10MANAGEMENT24507450 7934MILLERCLERK10REGULAR13007450 7839KINGPRESIDENT10MANAGEMENT50007450 7902FORDANALYST20REGULAR30002975 7788SCOTTANALYST20REGULAR30002975 7566JONESMANAGER20MANAGEMENT29752975 7369SMITHCLERK20REGULAR8002975 7876ADAMSCLERK20REGULAR11002975 7521WARDSALESMAN30REGULAR12502850 7654MARTINSALESMAN30REGULAR12502850 7844TURNERSALESMAN30REGULAR15002850 7900JAMESCLERK30REGULAR9502850 7499ALLENSALESMAN30REGULAR16002850 7698BLAKEMANAGER30MANAGEMENT28502850 Las filas se dividen en grupos en función de la columna dept_id. Hay tres grupos, uno por cada departamento. La función SUM() se aplica a la expresión CASE WHEN. En lugar de calcular el salario total de cada departamento, calculamos el salario total de los empleados que ocupan puestos directivos en el departamento. CASE devuelve 0 para los empleados normales (la suma no se incrementa) y el valor del salario para los empleados de dirección. Puede utilizar este patrón en muchas situaciones diferentes. De hecho, en la siguiente sección veremos otro ejemplo de combinación de CASE WHEN con SUM() y OVER(PARTITION BY). Ejemplo 5: Cálculo del total de un pedido con descuentos utilizando SUM() con CASE WHEN En este ejemplo, queremos calcular el valor total de cada pedido, incluyendo los descuentos de algunos artículos del pedido. Utilizaremos la sintaxis SUM() OVER(PARTITION BY …) para sumar todos los valores de los artículos por pedido. Y para incorporar los descuentos de los productos, utilizaremos la sentencia CASE WHEN. Utilizamos la tabla order_items de los datos de ejemplo proporcionados por Oracle Live SQL. Esta tabla almacena todos los artículos del pedido (product_id) pertenecientes a cada pedido (order_id). Contiene información sobre el precio unitario del producto (unit_price) y la cantidad del pedido (quantity). Ahora queremos calcular los valores del pedido: uno por cada producto del pedido y un total para el pedido; el total del pedido debe incluir cualquier descuento aplicado a los productos. El total del pedido es igual al precio unitario multiplicado por la cantidad del pedido. Sin embargo, cuando se aplica un descuento a un producto, utilizaremos un extracto de CASE WHEN para contabilizarlo. SELECT order_id, product_id, unit_price, quantity, SUM(CASE -- 20% discount for this product WHEN product_id = 3143 THEN unit_price*quantity*0.8 -- 40% discount for this product WHEN product_id = 3106 THEN unit_price*quantity*0.6 ELSE unit_price*quantity END) OVER(PARTITION BY order_id, product_id) AS order_product_total_with_discount, SUM(CASE -- 20% discount for this product WHEN product_id = 3143 THEN unit_price*quantity*0.8 -- 40% discount for this product WHEN product_id = 3106 THEN unit_price*quantity*0.6 ELSE unit_price*quantity END) OVER(PARTITION BY order_id) AS order_total_with_discount FROM order_items; ORDER_IDPRODUCT_IDUNIT_PRICEQUANTITYORDER_PRODUCT_TOTAL_WITH_DISCOUNTORDER_TOTAL_WITH_DISCOUNT 2354310648611756.844916.2 2354311496.8434162.444916.2 235431237947371344916.2 235431294147192744916.2 235431392148100844916.2 235431431653678.444916.2 23543150175898644916.2 235431633061183044916.2 235431653764236844916.2 235431675168346844916.2 23543170145.2701016444916.2 23543176113.3728157.644916.2 235431826177469744916.2 2355228946200920094513.5 23552308571851054594513.5 2355231186.918816337.294513.5 2355232219188357294513.5 2355232317190323094513.5 235523261.1192211.294513.5 235523301.1197216.794513.5 2355233925199497594513.5 23552359226.620446226.494513.5 Para calcular el total por producto en un pedido, utilizamos la siguiente sintaxis: SUM(CASE WHEN product_id=3143 THEN unit_price*quantity*0.8 -- 20% discount WHEN product_id=3106 THEN unit_price*quantity*0.6 -- 40% discount ELSE unit_price*quantity END) OVER(PARTITION BY order_id, product_id) AS order_product_total_with_discount Pasamos la sentencia CASE WHEN como argumento a la función SUM(); si el ID de producto de la fila actual es 3143, aplicamos un descuento del 20%; para el ID de producto 3106, el descuento es del 40%. A continuación, dividimos el conjunto de datos por ID de pedido e ID de producto para obtener los valores totales de cada producto de un pedido. Observe que utilizamos dos cláusulas PARTITION BY diferentes en la consulta. Para calcular el valor total del producto, dividimos el conjunto de datos por ID de pedido e ID de producto. Para calcular el total por pedido, dividimos el conjunto de datos sólo por ID de pedido. El valor total por pedido es igual para todas las filas con el mismo ID de pedido. Es decir, si se suman todos los valores totales de los productos de un determinado pedido, se obtiene el valor total del pedido. Por ejemplo, para el ID de pedido 2355, obtenemos lo siguiente 9200 + 10545 + 16337.2 + 3572 + 3230 + 211.2 + 216.7 + 4975 + 46226.4 = 94513.5. Aquí tienes algunos ejemplos de la función SUM() con CASE WHEN. Siga adelante y SUM() con OVER() y PARTITION BY Ahora que sabe cómo utilizar la función de ventana SUM() y sus diversas opciones de sintaxis, puede probarla usted mismo. Presentamos ejemplos sobre cómo calcular un porcentaje de un valor de una fila al total de la partición y mostramos cómo calcular el total corrido y el total de orden personalizado. Le animamos a que practique con sus propios datos. Para aprender más, pruebe nuestro curso interactivo Funciones de ventana que explica en detalle todos los conceptos de las funciones de ventana. O consulte nuestra Funciones de ventana Cheat Sheet si desea una referencia rápida y sencilla de las funciones de ventana de SQL. Mucha suerte. Tags: SQL PARTITION BY funciones de ventana