21st Jul 2022 Lectura de 11 minutos ¿Cuándo debo utilizar las funciones de ventana de SQL? Tihomir Babic SQL aprender SQL funciones de ventana Índice ¿Qué es Funciones de ventana? Ejemplo 1: Calcular el salario medio y comparar el salario de Individual con la media Ejemplo 2: Calcular el número medio de productos vendidos por fecha y región Ejemplo 3: Calcular la suma acumulada de productos vendidos por región Ejemplo 4: Comparar los precios de las acciones con los precios mínimos y máximos del mercado Ejemplo 5: Calcular el porcentaje de cambio de precio y las medias móviles ¿Crees que aprender Funciones de ventana puede ayudarte en tu trabajo? ¿Ha oído a alguno de sus colegas presumir de utilizar las funciones de ventana de SQL? ¿Conoce el SQL básico pero no sabe mucho, o nada, sobre las funciones de ventana? Si quieres aprender sobre las funciones de ventana y cómo utilizarlas en un contexto empresarial, estás en el lugar adecuado. Esto sucede a menudo. Alcanzas un cierto nivel de conocimientos y te sientes el rey (o la reina) del mundo. Entonces, oyes a tus colegas hablar de algo de lo que nunca has oído hablar (en este caso, las funciones de ventana). Inmediatamente te sientes un poco avergonzado por no conocer ya las funciones de ventana. ¿Le resulta familiar? Este sentimiento no es agradable. Pero puede ser bueno si te lleva a preguntar qué son las funciones de ventana. Entonces, lo buscas en Google y encuentras algunos artículos útiles (como éste). De repente, la vergüenza se convertirá en empoderamiento cuando te des cuenta de que las funciones de ventana no son misteriosas ni inaprensibles. De nuevo, te sientes el rey del mundo. O la reina. Quizá incluso las dos cosas. ¡Avancemos hacia esta sensación de realeza! Intentaré no bombardearte con SQL. En su lugar, haré el camino inverso. Daré varios ejemplos empresariales del mundo real que te mostrarán el uso práctico de las funciones de ventana. ¿Qué es Funciones de ventana? Una función ventana es, en pocas palabras, una función que realiza cálculos en un conjunto de filas de la tabla. El nombre proviene del hecho de que el conjunto de filas se llama ventana o marco de ventana. Este es un ejemplo del aspecto de una ventana. En la tabla de abajo, las ventanas están marcadas con diferentes colores. La suma acumulada se calcula para cada región, por lo que en este caso, las ventanas se definen por región. dateregionproducts_soldcumulative_sum 2020-03-01Region 19999 2020-03-02Region 198197 2020-03-03Region 143240 2020-03-01Region 29696 2020-03-02Region 259155 2020-03-03Region 229184 2020-03-01Region 37676 2020-03-02Region 350126 2020-03-03Region 370196 La sintaxis de la función ventana es: window_function ([ALL] expression) OVER ([PARTITION BY partition_list] [ORDER BY order_list] [window_frame_clause]) La parte de la sintaxis de la función ventana puede ser una función agregada, como SUM() o AVG(). También puede ser otro tipo de función, como una función analítica o de clasificación. La ventana, o el número de filas sobre las que se realizarán ciertos cálculos, se define mediante la cláusula OVER(). PARTITION BY es una cláusula opcional en las funciones de ventana. Define una partición sobre la que la función ventana realizará la operación. Si no se define PARTITION BY, la función ventana realizará la operación en toda la tabla. Puede obtener más información en este artículo. ORDER BY ordenará las filas dentro de cada partición en el orden deseado. Si no se define esta cláusula, entonces la cláusula utilizará toda la tabla. La cláusula de marco de ventana define el número de filas sobre las que operará la función de ventana utilizando dos palabras clave. Una es ROWS, utilizada para limitar el número de filas especificando el número de filas que preceden o siguen a la fila actual. La otra es RANGE, utilizada para limitar el número de filas especificando un rango de valores con respecto al valor de la fila actual. Por eso la cláusula de marco de ventana también se llama cláusula ROW o RANGE. Para aprender a utilizar esta sintaxis y practicarla, el curso LearnSQL.es sobre funciones de ventana es el lugar adecuado. Además, si te interesa una mayor explicación de las funciones de ventana, puedes encontrarla aquí, junto con algunos ejemplos. Pasemos ahora a la parte divertida, ¡la resolución de problemas! Ejemplo 1: Calcular el salario medio y comparar el salario de Individual con la media Este es un ejemplo sencillo de un problema común en el mundo de los negocios. Digamos que hay una tabla employeeque contiene datos sobre los salarios de los empleados. Consta de las siguientes filas: id - id único first_name - nombre del empleado last_name - apellido del empleado department - departamento del empleado salary - salario mensual del empleado Con estos datos, primero hay que calcular el salario medio de toda la empresa. A continuación, tienes que calcular cuánto está por encima o por debajo del salario medio de cada empleado. El siguiente código lo hará rápidamente: SELECT first_name, last_name, department, salary, AVG(salary) OVER() AS avg_salary, salary - AVG(salary) OVER() AS diff_salary FROM employee; Como estás familiarizado con SQL, probablemente reconozcas al menos parte de este código. Selecciona first_name, last_name, department, y salary de la tabla employee. No hay nada nuevo aquí. La línea AVG(salary) OVER() AS avg_salary calcula el salario medio en la ventana definida por OVER(). El resultado se mostrará en la columna avg_salary. La línea salary - AVG(salary) OVER() AS diff_salary calcula la diferencia entre el salario de cada empleado y el salario medio, El resultado se mostrará en la columna diff_salary. Al ejecutar este código se obtendrá una tabla útil. Vea un extracto de la misma a continuación: first_namelast_namedepartmentsalaryavg_salarydiff_salary EvangelinaChesshireTraining1,0152,469-1,454 JudDunkerleyLegal3,579.32,4691,111 EssaOdoSupport786.82,469-1,682 SaudraBolducServices609.22,469-1,860 GarveyJefferysSales4,600.22,4692,132 MaryjaneDumbrellServices590.92,469-1,878 RicaSiburnEngineering4,353.82,4691,885 ArlindaKilminsterSales3,891.92,4691,423 VerenaDevinnResearch and Development1,093.52,469-1,375 GerdaLegendreServices3,863.92,4691,395 Ejemplo 2: Calcular el número medio de productos vendidos por fecha y región Imagine que trabaja en una empresa que opera en tres regiones. La dirección quiere saber el número medio de productos vendidos en cada región. Además, quieren saber el número medio de productos vendidos en general para cada fecha. Las funciones de ventana le permitirán hacerlo fácilmente. En este ejemplo, los datos se almacenan en la tabla sales que tiene tres columnas: date - fecha de la venta del producto region - nombre de la región products_sold - número de productos vendidos Aquí está el código necesario para crear ese informe: SELECT date, region, products_sold, AVG(products_sold) OVER(PARTITION BY date) AS avg_date, AVG(products_sold) OVER(PARTITION BY region) AS avg_region FROM sales ORDER BY region, date; Este código selecciona las columnas date, region, y products_sold. Luego, calcula el promedio de productos vendidos en cada fecha. Esto está definido por la cláusula PARTITION BY(). El resultado se mostrará en la columna avg_date. La siguiente línea también calcula el número medio de productos vendidos, esta vez en cada región. El resultado se mostrará en la columna avg_region. A continuación, el resultado se ordena por la región y la fecha utilizando la cláusula ORDER BY. Vea los resultados a continuación: dateregionproducts_soldavg_dateavg_region 2020-03-01Region 19990.33333380 2020-03-02Region 1986980 2020-03-03Region 14347.33333380 2020-03-01Region 29690.33333361.333333 2020-03-02Region 2596961.333333 2020-03-03Region 22947.33333361.333333 2020-03-01Region 37690.33333365.333333 2020-03-02Region 3506965.333333 2020-03-03Region 37047.33333365.333333 Ejemplo 3: Calcular la suma acumulada de productos vendidos por región La gerencia estaba contenta con su informe anterior. Ahora, quieren que calcule la suma acumulativa (o el total acumulado) de los productos vendidos en cada región. Las funciones de ventana son útiles para realizar estos cálculos. El cálculo se realizará en la tabla sales utilizada en el ejemplo 2. Este código le permitirá entregar rápidamente los números requeridos: SELECT date, region, products_sold, SUM(products_sold) OVER(PARTITION BY region ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cumulative_region FROM sales ORDER BY region, date; La primera parte del código selecciona las mismas columnas que el código del Ejemplo 2. Luego, calcula la suma de los productos por región. Esto está definido por la cláusula PARTITION BY(). Por supuesto, se necesita la suma acumulada, no la suma total. Por eso se ordena la ventana por la fecha utilizando el comando ORDER BY. Ahora que todo está definido, hay que decirle a SQL que sume el valor de la fila actual a la suma de las filas anteriores dentro de la ventana. Esto se hace mediante ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. La función de ventana sumará todas las filas anteriores a la fila actual (por eso UNBOUNDED PRECEDING) y ninguna fila posterior a la fila actual (por eso CURRENT ROW) dentro de la ventana especificada. El resultado se mostrará en la columna cumulative_region. El resultado se ordenará por la región y la fecha, como en el ejemplo anterior. Después de ejecutar el código, obtendrá la siguiente tabla: dateregionproducts_soldcumulative_region 2020-03-01Region 19999 2020-03-02Region 198197 2020-03-03Region 143240 2020-03-01Region 29696 2020-03-02Region 259155 2020-03-03Region 229184 2020-03-01Region 37676 2020-03-02Region 350126 2020-03-03Region 370196 Ejemplo 4: Comparar los precios de las acciones con los precios mínimos y máximos del mercado Su empresa está monitoreando los precios de las acciones en NASDAQ y NYSE. La gerencia quiere que usted calcule los precios mínimos y máximos de las acciones en ambos mercados en los últimos 365 días. También quieren ver cómo el precio de cada acción negociada en 2020 difiere del precio mínimo y máximo en el mercado. La tabla stockprice contiene datos del 15/3/2019 al 14/3/2020 y consta de las siguientes columnas: date - fecha de la negociación stock_name - nombre de la acción stock_price - precio de la acción stock_market - mercado en el que se negocia la acción max_price - precio máximo en el mercado en los últimos 365 días min_price - precio mínimo en el mercado en los últimos 365 días diff_max - precio de la acción menos el precio máximo en el mercado en los últimos 365 días diff_min - precio de la acción menos el precio mínimo en el mercado en los últimos 365 días El código que creará rápidamente el informe solicitado tiene el siguiente aspecto: SELECT date, stock_name, stock_price, stock_market, MAX(stock_price) OVER(PARTITION BY stock_market) as max_price, MIN(stock_price) OVER(PARTITION BY stock_market) as min_price, stock_price - MAX(stock_price) OVER(PARTITION BY stock_market) AS diff_max, stock_price - MIN(stock_price) OVER(PARTITION BY stock_market) AS diff_min FROM stockprice WHERE date > '2019-12-31' ORDER BY date; La primera parte del código selecciona las columnas originales de la tabla: date, stock_name, stock_price, y stock_market. Luego, la función de ventana MAX() con la cláusula PARTITION BY calcula el precio máximo para cada mercado, NASDAQ y NYSE, por separado. El resultado se mostrará en la columna max_price. La siguiente línea de código funciona de la misma manera, excepto que ahora calcula el precio mínimo. El resultado se mostrará en la columna min_price. Las siguientes líneas de código calculan la diferencia entre el precio de la acción y el precio máximo y mínimo, respectivamente, para cada mercado. Los resultados se mostrarán en las columnas diff_max y diff_min. Como el informe debe mostrar sólo los datos de 2020, he utilizado la cláusula WHERE. Por último, la tabla resultante está ordenada por la fecha, lo cual es lógico para un informe de este tipo. Este es el aspecto de las primeras filas del informe: datestock_namestock_pricestock_marketmax_pricemin_pricediff_maxdiff_min 1.1.2020MYOS RENS Technology Inc.91.49NASDAQ99.7530.37-8.2660.39 1.1.2020Huron Consulting Group Inc.59.56NASDAQ99.7530.37-40.1928.46 1.1.2020Sensient Technologies Corporation82.05NYSE99.5430.37-17.4951.68 2.1.2020Regions Financial Corporation46.75NYSE99.5430.37-52.7916.38 2.1.2020Ottawa Bancorp, Inc.51.55NASDAQ99.7530.37-48.220.45 3.1.2020Vanguard Long-Term Government Bond ETF70.62NASDAQ99.7530.37-29.1339.52 3.1.2020Bruker Corporation52.99NASDAQ99.7530.37-46.7621.89 Ejemplo 5: Calcular el porcentaje de cambio de precio y las medias móviles La dirección sabe ahora que puede entregar informes con gran precisión y rapidez. Están impresionados. No se dan cuenta de que usted ha estado aprendiendo las funciones de la ventana SQL y que lo que le pidieron es fácil para usted. A continuación, le piden algo que debería llevarle mucho más tiempo. Pero no lo hará. Tienes una tabla de precios que contiene todos los price cambios de una acción en 2020. A veces sólo hay un cambio diario, a veces hay más. La tabla consta de las siguientes columnas: date - fecha de la cotización stock_price - precio de la acción La dirección te ha pedido que les envíes un informe que tome cada precio y lo compare con el precio anterior. Además, te han pedido que calcules la media móvil del precio de las acciones. Así es como lo harás: SELECT date, stock_price, (stock_price/LAG(stock_price) OVER(ORDER BY date)) - 1 AS percent_change, AVG(stock_price) OVER(ORDER BY date ROWS BETWEEN 0 PRECEDING AND 4 FOLLOWING) AS moving_avg FROM price; ¿Qué hace este código? Primero, selecciona las columnas originales de la tabla: date y stock_price. La siguiente línea introduce una nueva función de ventana, LAG(). Esta función accede a los datos de la fila anterior, lo que es ideal para esta tarea. El stock_price se divide por el precio anterior (de ahí la función LAG() ). A continuación, se resta 1 al resultado para obtener un porcentaje. El resultado se mostrará en la columna percent_change. La siguiente línea calcula la media móvil. Utiliza la función de ventana AVG(), que ya conoces. En la cláusula OVER(), los datos se ordenan por la fecha. La dirección no ha especificado cómo quiere que se calcule la media móvil. Así que he decidido calcularla utilizando cinco cambios de precio, lo que se especifica en ROWS BETWEEN 0 PRECEDING AND 4 FOLLOWING. Al calcular la media móvil, el código tendrá en cuenta la fila actual y las cuatro filas siguientes, es decir, cinco en total. Puede jugar con esa parte del código, ya que no hay un número definido de datos que deban tenerse en cuenta al calcular las medias móviles. Depende de la cantidad y el tipo de datos, así como de las preferencias individuales. Cambiando los números que vienen antes de PRECEDING y FOLLOWING, puede cambiar fácil y rápidamente el cálculo, dependiendo de la metodología que decida utilizar. Vea los resultados a continuación: datestock_pricepercent_changemoving_avg 1.1.201936.37NULL39.126 1.1.201937.890.041792637.922 1.1.201944.080.163367638.768 2.1.201930.43-0.309664340.84 3.1.201946.860.539927741.058 3.1.201930.35-0.352326143.3 3.1.201942.120.387808845.276 4.1.201954.440.292497648.452 5.1.201931.52-0.42101448.78 6.1.201958.070.842322352.822 7.1.201940.23-0.307215549.19 ¿Crees que aprender Funciones de ventana puede ayudarte en tu trabajo? He dado ejemplos de negocios del mundo real como punto de partida en lugar de un puro análisis de código de funciones de ventana. Los cinco ejemplos son algo que he tratado en mi carrera. Esta es la forma en que aprendí SQL. Primero, tuve un problema que resolver. Luego, traté de averiguar cómo hacerlo usando SQL. Si crees que las funciones de ventana serán útiles para tu trabajo, este curso de LearnSQL.es es una buena manera de aprender más. Si has encontrado estos ejemplos interesantes o quieres compartir algunos de tus ejemplos del mundo real, ¡siéntete libre de comentar abajo! Tags: SQL aprender SQL funciones de ventana