5

Window Functions in MySQL 8.0

 2 years ago
source link: https://www.percona.com/blog/window-functions-in-mysql-8-0/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Window Functions in MySQL 8.0

Window Functions in MySQL 8.0I have recently written an article for this blog presenting Window Functions for MongoDB 5.0. I used some public Italian COVID-19 data for a few real examples. Please have a look at it if you like.

Then I thought I should provide the same even for a relational database like MySQL.

MySQL introduced Window Functions in version 8.0. This feature has been in demand by many developers for some time. In this article, I’m going to show the benefits and how you can use Window Functions on MySQL 8.0.

Load some public data

I have a Percona Server for MySQL 8.0 running and I got some public Italian data about COVID-19 infections, hospitalizations, and other info. The data are available on a per-day and per-region basis from the following link:

https://github.com/pcm-dpc/COVID-19/tree/master/dati-regioni.

I loaded just a few months’ data spanning 2021 and 2022. Original data is labeled in Italian, so I created a similar and reduced table just for the needs of this article.

Here is a sample of the data:

Shell
mysql> DESC covid;
+----------------+--------------+------+-----+---------+----------------+
| Field          | Type         | Null | Key | Default | Extra          |
+----------------+--------------+------+-----+---------+----------------+
| id             | int unsigned | NO   | PRI | NULL    | auto_increment |
| day            | date         | YES  |     | NULL    |                |
| region         | varchar(50)  | YES  |     | NULL    |                |
| total_cases    | int unsigned | YES  |     | NULL    |                |
| deceased       | int unsigned | YES  |     | NULL    |                |
| hospitalized   | int unsigned | YES  |     | NULL    |                |
| intensive_care | int unsigned | YES  |     | NULL    |                |
| home_isolation | int unsigned | YES  |     | NULL    |                |
+----------------+--------------+------+-----+---------+----------------+
mysql> SELECT * FROM covid LIMIT 5;
+----+------------+----------------+-------------+----------+--------------+----------------+----------------+
| id | day        | region         | total_cases | deceased | hospitalized | intensive_care | home_isolation |
+----+------------+----------------+-------------+----------+--------------+----------------+----------------+
|  1 | 2021-10-01 | Abruzzo        |       81281 |     2545 |           56 |              4 |           1677 |
|  2 | 2021-10-01 | Basilicata     |       30175 |      614 |           38 |              2 |           1214 |
|  3 | 2021-10-01 | Calabria       |       83918 |     1408 |          156 |             15 |           3359 |
|  4 | 2021-10-01 | Campania       |      456695 |     7944 |          233 |             21 |           6578 |
|  5 | 2021-10-01 | Emilia-Romagna |      424089 |    13477 |          416 |             46 |          13882 |
+----+------------+----------------+-------------+----------+--------------+----------------+----------------+

What are Window Functions

Window Functions permit the run of a window across sorted rows producing calculations over each step of the window. As a consequence, a result of the Window Functions is provided for each row returned by the query.

The main advantage of Window Functions is that you can run aggregations on the fly in more efficient and elegant ways, without the need of creating temporary tables or views to use for further queries.

Typical use cases are calculating rolling averages, correlation scores, or cumulative totals.

Two new clauses are used to define and use Windows Functions: OVER and WINDOW. The second one is not mandatory. We’ll see some examples to show how you can use them.

The first example: hospitalizations in Central Italy area

Let’s focus our attention on the specific area of “Central Italy” which includes the following five regions: Toscana, Umbria, Marche, Lazio, and Abruzzo.

We’d like to find out the number of hospitalizations per day in each region and also calculate the total of hospitalizations for the entire area for a specific period, the first week of December 2021.

Shell
mysql> SELECT day, region, hospitalized,
    -> SUM(hospitalized) OVER(PARTITION BY day) AS 'total_hospitalized'
    -> FROM covid
    -> WHERE region IN ('Toscana','Umbria','Lazio','Marche','Abruzzo')
    -> AND day BETWEEN '2021-12-01' AND '2021-12-06';
+------------+---------+--------------+--------------------+
| day        | region  | hospitalized | total_hospitalized |
+------------+---------+--------------+--------------------+
| 2021-12-01 | Lazio   |          792 |               1384 |
| 2021-12-01 | Abruzzo |          115 |               1384 |
| 2021-12-01 | Umbria  |           57 |               1384 |
| 2021-12-01 | Toscana |          307 |               1384 |
| 2021-12-01 | Marche  |          113 |               1384 |
| 2021-12-02 | Abruzzo |          118 |               1371 |
| 2021-12-02 | Lazio   |          785 |               1371 |
| 2021-12-02 | Marche  |          117 |               1371 |
| 2021-12-02 | Toscana |          298 |               1371 |
| 2021-12-02 | Umbria  |           53 |               1371 |
| 2021-12-03 | Abruzzo |          123 |               1408 |
| 2021-12-03 | Lazio   |          815 |               1408 |
| 2021-12-03 | Marche  |          123 |               1408 |
| 2021-12-03 | Toscana |          294 |               1408 |
| 2021-12-03 | Umbria  |           53 |               1408 |
| 2021-12-04 | Umbria  |           47 |               1383 |
| 2021-12-04 | Toscana |          295 |               1383 |
| 2021-12-04 | Marche  |          126 |               1383 |
| 2021-12-04 | Abruzzo |          112 |               1383 |
| 2021-12-04 | Lazio   |          803 |               1383 |
| 2021-12-05 | Abruzzo |          122 |               1408 |
| 2021-12-05 | Lazio   |          811 |               1408 |
| 2021-12-05 | Marche  |          126 |               1408 |
| 2021-12-05 | Toscana |          299 |               1408 |
| 2021-12-05 | Umbria  |           50 |               1408 |
| 2021-12-06 | Lazio   |          864 |               1472 |
| 2021-12-06 | Umbria  |           50 |               1472 |
| 2021-12-06 | Toscana |          300 |               1472 |
| 2021-12-06 | Marche  |          130 |               1472 |
| 2021-12-06 | Abruzzo |          128 |               1472 |
+------------+---------+--------------+--------------------+
30 rows in set (0.00 sec)

In this example, the SUM() function works as a window function that operates on a set of rows defined by the contents of the OVER clause. Many other aggregation functions you regularly use with GROUP BY can be used as window functions this way. The OVER clause does the magic by defining the window’s set of rows. Here, the PARTITION BY day tells MySQL to consider as a window all the rows having the same value for the day column, and then calculate the SUM() over those rows only. The main difference between using the aggregation function with GROUP BY or as a window function is that in the first case a single row is returned for each group, in the second case all the rows are returned and the aggregated value is returned for each row.

The following picture shows with different colors how the windows are considered for this query:

window_function..png

Multiple window functions in one query

Here is another example to show you can create multiple windows inside a query. Each one must have its own OVER clause to define the partition.

In the following query, we would like to return the number of deceased on average for the entire country in January 2022. Also, we would like to return the maximum number of deceased for each region in the period.

Shell
mysql> SELECT day, region, deceased,
    -> AVG(deceased) OVER() AS 'country average deceased'
    -> MAX(deceased) OVER(PARTITION BY region) AS 'max daily deceased in the period'
    -> FROM covid
    -> WHERE day BETWEEN '2022-01-01' AND '2022-01-31'
    -> ORDER BY day, region;
+------------+-----------------------+----------+--------------------------+----------------------------------+
| day        | region                | deceased | country average deceased | max daily deceased in the period |
+------------+-----------------------+----------+--------------------------+----------------------------------+
| 2022-01-01 | Abruzzo               |     2640 |                6737.0000 |                             2811 |
| 2022-01-01 | Basilicata            |      635 |                6737.0000 |                              681 |
| 2022-01-01 | Calabria              |     1625 |                6737.0000 |                             1887 |
| 2022-01-01 | Campania              |     8471 |                6737.0000 |                             9139 |
| 2022-01-01 | Emilia-Romagna        |    14231 |                6737.0000 |                            15088 |
| 2022-01-01 | Friuli Venezia Giulia |     4225 |                6737.0000 |                             4487 |
| 2022-01-01 | Lazio                 |     9275 |                6737.0000 |                             9823 |
| 2022-01-01 | Liguria               |     4587 |                6737.0000 |                             4873 |
| 2022-01-01 | Lombardia             |    35095 |                6737.0000 |                            37184 |
| 2022-01-01 | Marche                |     3249 |                6737.0000 |                             3418 |
| 2022-01-01 | Molise                |      512 |                6737.0000 |                              528 |
| 2022-01-01 | P.A. Bolzano          |     1307 |                6737.0000 |                             1357 |
| 2022-01-01 | P.A. Trento           |     1423 |                6737.0000 |                             1473 |
| 2022-01-01 | Piemonte              |    12059 |                6737.0000 |                            12601 |
| 2022-01-01 | Puglia                |     6987 |                6737.0000 |                             7215 |
| 2022-01-01 | Sardegna              |     1729 |                6737.0000 |                             1844 |
| 2022-01-01 | Sicilia               |     7514 |                6737.0000 |                             8527 |
| 2022-01-01 | Toscana               |     7562 |                6737.0000 |                             8263 |
| 2022-01-01 | Umbria                |     1504 |                6737.0000 |                             1623 |
| 2022-01-01 | Valle d'Aosta         |      488 |                6737.0000 |                              507 |
| 2022-01-01 | Veneto                |    12395 |                6737.0000 |                            13169 |
| 2022-01-02 | Abruzzo               |     2642 |                6737.0000 |                             2811 |
| 2022-01-02 | Basilicata            |      635 |                6737.0000 |                              681 |
| 2022-01-02 | Calabria              |     1630 |                6737.0000 |                             1887 |
| 2022-01-02 | Campania              |     8474 |                6737.0000 |                             9139 |
| 2022-01-02 | Emilia-Romagna        |    14239 |                6737.0000 |                            15088 |
| 2022-01-02 | Friuli Venezia Giulia |     4228 |                6737.0000 |                             4487 |
| 2022-01-02 | Lazio                 |     9290 |                6737.0000 |                             9823 |
| 2022-01-02 | Liguria               |     4591 |                6737.0000 |                             4873 |
| 2022-01-02 | Lombardia             |    35140 |                6737.0000 |                            37184 |
| 2022-01-02 | Marche                |     3252 |                6737.0000 |                             3418 |
| 2022-01-02 | Molise                |      512 |                6737.0000 |                              528 |
| 2022-01-02 | P.A. Bolzano          |     1308 |                6737.0000 |                             1357 |
| 2022-01-02 | P.A. Trento           |     1423 |                6737.0000 |                             1473 |
| 2022-01-02 | Piemonte              |    12065 |                6737.0000 |                            12601 |
| 2022-01-02 | Puglia                |     6987 |                6737.0000 |                             7215 |
| 2022-01-02 | Sardegna              |     1731 |                6737.0000 |                             1844 |
| 2022-01-02 | Sicilia               |     7527 |                6737.0000 |                             8527 |
| 2022-01-02 | Toscana               |     7568 |                6737.0000 |                             8263 |
| 2022-01-02 | Umbria                |     1508 |                6737.0000 |                             1623 |
| 2022-01-02 | Valle d'Aosta         |      488 |                6737.0000 |                              507 |
| 2022-01-02 | Veneto                |    12408 |                6737.0000 |                            13169 |
too many lines. Truncated!

As you can notice, we defined two window functions. The special case of OVER(), without any argument, means the entire result set is considered to apply the aggregation function. The second OVER clause defines partitions based on the region field.

Calculate daily new cases, the non-aggregate functions

Since we have in the table only the number of total cases, we would like to calculate the number of new cases on a per-day basis instead. This way we can understand if the status of the pandemic is getting worse or improving.

We need to define a Window Function to span the previous day’s row and calculate the difference between today’s total cases and yesterday’s total cases.

You can use the following query where a new special “non-aggregate” function is used.

Shell
mysql> SELECT region, day, total_cases,
    -> total_cases - LAG(total_cases) OVER(PARTITION BY region ORDER BY day ASC) AS 'new_cases'
    -> FROM covid
    -> WHERE day BETWEEN '2022-02-01' AND '2022-02-09';
+-----------------------+------------+-------------+-----------+
| region                | day        | total_cases | new_cases |
+-----------------------+------------+-------------+-----------+
| Abruzzo               | 2022-02-01 |      219045 |      NULL |
| Abruzzo               | 2022-02-02 |      221638 |      2593 |
| Abruzzo               | 2022-02-03 |      224389 |      2751 |
| Abruzzo               | 2022-02-04 |      226689 |      2300 |
| Abruzzo               | 2022-02-05 |      228922 |      2233 |
| Abruzzo               | 2022-02-06 |      231001 |      2079 |
| Abruzzo               | 2022-02-07 |      232079 |      1078 |
| Abruzzo               | 2022-02-08 |      235013 |      2934 |
| Abruzzo               | 2022-02-09 |      237059 |      2046 |
| Basilicata            | 2022-02-01 |       65200 |      NULL |
| Basilicata            | 2022-02-02 |       66235 |      1035 |
| Basilicata            | 2022-02-03 |       67252 |      1017 |
| Basilicata            | 2022-02-04 |       68168 |       916 |
| Basilicata            | 2022-02-05 |       69209 |      1041 |
| Basilicata            | 2022-02-06 |       70007 |       798 |
| Basilicata            | 2022-02-07 |       70435 |       428 |
| Basilicata            | 2022-02-08 |       71610 |      1175 |
| Basilicata            | 2022-02-09 |       72521 |       911 |
| Calabria              | 2022-02-01 |      171780 |      NULL |
| Calabria              | 2022-02-02 |      173814 |      2034 |
| Calabria              | 2022-02-03 |      176029 |      2215 |
| Calabria              | 2022-02-04 |      177441 |      1412 |
| Calabria              | 2022-02-05 |      178709 |      1268 |
| Calabria              | 2022-02-06 |      180565 |      1856 |
| Calabria              | 2022-02-07 |      181634 |      1069 |
| Calabria              | 2022-02-08 |      184087 |      2453 |
| Calabria              | 2022-02-09 |      185666 |      1579 |
too many lines. Truncated

The LAG function is a “non-aggregate” function introduced for the Window Functions usage only. The LAG function returns the value of the argument from the row lagging the current row within the partition. If nothing is specified as an argument, the previous row is considered. So, it’s our case, because we need yesterday’s total case to calculate the difference.

The LAG function can be also used as follows:

LAG(total_cases, 3)

In such a case it returns the value of total_cases from the row that lags (precedes) the current row by three rows within its partition.

Non-aggregate functions

We have introduced the LAG() function as non-aggregate. It is not the only one available. These functions perform for each row from a query, a calculation using rows related to that row.

The following table comes from the official documentation. There are all the available non-aggregate functions you can use with Window Functions.

non_aggregate_functions.png

Here is another example with some non-aggregate functions usage:

Shell
mysql> SELECT ROW_NUMBER() OVER(PARTITION BY region ORDER BY day ROWS UNBOUNDED PRECEDING) AS 'row number',
    -> region, day,
    -> FIRST_VALUE(home_isolation) OVER(PARTITION BY region ORDER BY day ROWS UNBOUNDED PRECEDING) AS 'first',
    -> LAST_VALUE(home_isolation) OVER(PARTITION BY region ORDER BY day ROWS UNBOUNDED PRECEDING) AS 'last'
    -> FROM covid
    -> WHERE day BETWEEN '2021-10-10' AND '2021-10-15';
+------------+-----------------------+------------+-------+-------+
| row number | region                | day        | first | last  |
+------------+-----------------------+------------+-------+-------+
|          1 | Abruzzo               | 2021-10-10 |  1439 |  1439 |
|          2 | Abruzzo               | 2021-10-11 |  1439 |  1360 |
|          3 | Abruzzo               | 2021-10-12 |  1439 |  1342 |
|          4 | Abruzzo               | 2021-10-13 |  1439 |  1332 |
|          5 | Abruzzo               | 2021-10-14 |  1439 |  1343 |
|          6 | Abruzzo               | 2021-10-15 |  1439 |  1374 |
|          1 | Basilicata            | 2021-10-10 |  1135 |  1135 |
|          2 | Basilicata            | 2021-10-11 |  1135 |  1117 |
|          3 | Basilicata            | 2021-10-12 |  1135 |  1104 |
|          4 | Basilicata            | 2021-10-13 |  1135 |  1102 |
|          5 | Basilicata            | 2021-10-14 |  1135 |  1055 |
|          6 | Basilicata            | 2021-10-15 |  1135 |  1028 |
|          1 | Calabria              | 2021-10-10 |  2818 |  2818 |
|          2 | Calabria              | 2021-10-11 |  2818 |  2752 |
|          3 | Calabria              | 2021-10-12 |  2818 |  2734 |
|          4 | Calabria              | 2021-10-13 |  2818 |  2707 |
|          5 | Calabria              | 2021-10-14 |  2818 |  2707 |
|          6 | Calabria              | 2021-10-15 |  2818 |  2738 |
|          1 | Campania              | 2021-10-10 |  6206 |  6206 |
|          2 | Campania              | 2021-10-11 |  6206 |  6024 |
|          3 | Campania              | 2021-10-12 |  6206 |  5843 |
|          4 | Campania              | 2021-10-13 |  6206 |  5797 |
|          5 | Campania              | 2021-10-14 |  6206 |  5881 |
|          6 | Campania              | 2021-10-15 |  6206 |  5900 |
too many lines. Truncated

For more details about non-aggregate functions, look at the official documentation: https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html

Named windows

Take a look at the last query executed. We have used multiple non-aggregate functions and we have defined multiple times the same window. We can simplify the query by defining only once the window providing a specific name. Then we can use that name to address the window without repeating the definition.

Then the previous query can be rewritten as follows:

Shell
mysql> SELECT ROW_NUMBER() OVER wf AS 'row_number',
    -> region, day,
    -> FIRST_VALUE(home_isolation) OVER wf AS 'first',
    -> LAST_VALUE(home_isolation) OVER wf AS 'last'
    -> FROM covid
    -> WHERE day BETWEEN '2021-10-10' AND '2021-10-15'
    -> WINDOW wf AS (PARTITION BY region ORDER BY day ROWS UNBOUNDED PRECEDING);
+------------+-----------------------+------------+-------+-------+
| row_number | region                | day        | first | last  |
+------------+-----------------------+------------+-------+-------+
|          1 | Abruzzo               | 2021-10-10 |  1439 |  1439 |
|          2 | Abruzzo               | 2021-10-11 |  1439 |  1360 |
|          3 | Abruzzo               | 2021-10-12 |  1439 |  1342 |
|          4 | Abruzzo               | 2021-10-13 |  1439 |  1332 |
|          5 | Abruzzo               | 2021-10-14 |  1439 |  1343 |
|          6 | Abruzzo               | 2021-10-15 |  1439 |  1374 |
|          1 | Basilicata            | 2021-10-10 |  1135 |  1135 |
|          2 | Basilicata            | 2021-10-11 |  1135 |  1117 |
|          3 | Basilicata            | 2021-10-12 |  1135 |  1104 |
|          4 | Basilicata            | 2021-10-13 |  1135 |  1102 |
|          5 | Basilicata            | 2021-10-14 |  1135 |  1055 |
|          6 | Basilicata            | 2021-10-15 |  1135 |  1028 |
too many lines. Truncated

You create the named window using the WINDOW clause at the end of the query. You provide a name and the partition definition, then you can reference that window simply by name in the OVER clauses.

Multiple Window Functions can be created and named in the same query, like in the following example:

Shell
mysql> SELECT region, day,
    -> FIRST_VALUE(home_isolation) OVER wf_full AS 'first_full',
    -> FIRST_VALUE(home_isolation) OVER wf_last4days AS 'first_last4days'
    -> FROM covid
    -> WHERE day BETWEEN '2021-12-01' AND '2021-12-10'
    -> WINDOW wf_full AS (PARTITION BY region ORDER BY day ROWS UNBOUNDED PRECEDING),
    -> wf_last4days AS (PARTITION BY region ORDER BY day ROWS BETWEEN 4 PRECEDING AND 0 FOLLOWING);
+-----------------------+------------+------------+-----------------+
| region                | day        | first_full | first_last4days |
+-----------------------+------------+------------+-----------------+
| Abruzzo               | 2021-12-01 |       4116 |            4116 |
| Abruzzo               | 2021-12-02 |       4116 |            4116 |
| Abruzzo               | 2021-12-03 |       4116 |            4116 |
| Abruzzo               | 2021-12-04 |       4116 |            4116 |
| Abruzzo               | 2021-12-05 |       4116 |            4116 |
| Abruzzo               | 2021-12-06 |       4116 |            4376 |
| Abruzzo               | 2021-12-07 |       4116 |            4593 |
| Abruzzo               | 2021-12-08 |       4116 |            4776 |
| Abruzzo               | 2021-12-09 |       4116 |            4958 |
| Abruzzo               | 2021-12-10 |       4116 |            4920 |
| Basilicata            | 2021-12-01 |       1046 |            1046 |
| Basilicata            | 2021-12-02 |       1046 |            1046 |
| Basilicata            | 2021-12-03 |       1046 |            1046 |
| Basilicata            | 2021-12-04 |       1046 |            1046 |
| Basilicata            | 2021-12-05 |       1046 |            1046 |
| Basilicata            | 2021-12-06 |       1046 |            1050 |
| Basilicata            | 2021-12-07 |       1046 |            1094 |
| Basilicata            | 2021-12-08 |       1046 |            1101 |
| Basilicata            | 2021-12-09 |       1046 |            1125 |
| Basilicata            | 2021-12-10 |       1046 |            1120 |
| Calabria              | 2021-12-01 |       4374 |            4374 |
| Calabria              | 2021-12-02 |       4374 |            4374 |
| Calabria              | 2021-12-03 |       4374 |            4374 |
| Calabria              | 2021-12-04 |       4374 |            4374 |
| Calabria              | 2021-12-05 |       4374 |            4374 |
| Calabria              | 2021-12-06 |       4374 |            4537 |
| Calabria              | 2021-12-07 |       4374 |            4701 |
| Calabria              | 2021-12-08 |       4374 |            5050 |
| Calabria              | 2021-12-09 |       4374 |            5152 |
| Calabria              | 2021-12-10 |       4374 |            5233 |
too many lines. Truncated

Frame specification

As already shown in the queries we have tested so far, we can provide a frame clause when defining the Window Function. A frame is a subset of the current partition and the frame clause specifies how to define the subset.

Frames are determined with respect to the current row, which enables a frame to move within a partition depending on the location of the current row within its partition.

Shell
mysql> SELECT region, day,
    -> SUM(intensive_care) OVER(PARTITION BY region ORDER BY day ROWS UNBOUNDED PRECEDING) AS 'running_total',
    -> AVG(intensive_care) OVER(PARTITION BY region ORDER BY day ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS 'running_average'
    -> FROM covid
    -> WHERE day BETWEEN '2022-01-01' AND '2022-01-10';
+-----------------------+------------+---------------+-----------------+
| region                | day        | running_total | running_average |
+-----------------------+------------+---------------+-----------------+
| Abruzzo               | 2022-01-01 |            21 |         21.5000 |
| Abruzzo               | 2022-01-02 |            43 |         21.6667 |
| Abruzzo               | 2022-01-03 |            65 |         22.3333 |
| Abruzzo               | 2022-01-04 |            88 |         23.0000 |
| Abruzzo               | 2022-01-05 |           112 |         23.6667 |
| Abruzzo               | 2022-01-06 |           136 |         24.3333 |
| Abruzzo               | 2022-01-07 |           161 |         25.3333 |
| Abruzzo               | 2022-01-08 |           188 |         26.3333 |
| Abruzzo               | 2022-01-09 |           215 |         26.3333 |
| Abruzzo               | 2022-01-10 |           240 |         26.0000 |
| Basilicata            | 2022-01-01 |             1 |          1.5000 |
| Basilicata            | 2022-01-02 |             3 |          1.6667 |
| Basilicata            | 2022-01-03 |             5 |          2.3333 |
| Basilicata            | 2022-01-04 |             8 |          2.6667 |
| Basilicata            | 2022-01-05 |            11 |          2.6667 |
| Basilicata            | 2022-01-06 |            13 |          2.3333 |
| Basilicata            | 2022-01-07 |            15 |          2.0000 |
| Basilicata            | 2022-01-08 |            17 |          2.0000 |
| Basilicata            | 2022-01-09 |            19 |          2.0000 |
| Basilicata            | 2022-01-10 |            21 |          2.0000 |
| Calabria              | 2022-01-01 |            28 |         28.0000 |
| Calabria              | 2022-01-02 |            56 |         28.3333 |
| Calabria              | 2022-01-03 |            85 |         28.6667 |
| Calabria              | 2022-01-04 |           114 |         29.0000 |
| Calabria              | 2022-01-05 |           143 |         29.3333 |
| Calabria              | 2022-01-06 |           173 |         30.3333 |
| Calabria              | 2022-01-07 |           205 |         31.3333 |
| Calabria              | 2022-01-08 |           237 |         32.6667 |
| Calabria              | 2022-01-09 |           271 |         33.3333 |
| Calabria              | 2022-01-10 |           305 |         34.0000 |
too many lines. Truncated

The boundaries of the frame specification can include:

  • UNBOUNDED PRECEDING: frame starts at the first row of the partition.
  • N PRECEDING: a physical N of rows before the first current row. N can be a literal number or an expression that evaluates to a number.
  • CURRENT ROW: the row of the current calculation
  • UNBOUNDED FOLLOWING: the frame ends at the final row in the partition.
  • N FOLLOWING: a physical N of rows after the current row.

Conclusion

Windows Functions is a new amazing feature introduced in MySQL 8.0. This feature permits us to execute fewer and more efficient queries to solve specific problems. Without Window Functions, you may be forced to create temporary tables or not efficient views to achieve the same result by running multiple queries.

For more details, you can take a look at the official documentation:
https://dev.mysql.com/doc/refman/8.0/en/window-functions.html

Test the Window Functions on Percona Server for MySQL 8.0.

STAY UP-TO-DATE With Percona!

p

Join 50,000+ of your fellow open-source enthusiasts! Our newsletter provides updates on Percona open source software releases, technical resources, and valuable MySQL, MariaDB, PostgreSQL, and MongoDB-related articles. Get information about Percona Live, our technical webinars, and upcoming events and meetups where you can talk with our experts.

Enter your work email address:*

By submitting my information I agree that Percona may use my personal data in send communication to me about Percona services. I understand that I can unsubscribe from the communication at any time in accordance with the Percona Privacy Policy.

Author

Corrado Pandiani

Prior to joining Percona as a Senior Consultant, Corrado spent more than 20 years in developing web sites and designing and administering MySQL. He is a MySQL enthusiast since version 3.23 and his skills are focused on performances and architectural design. He's also a trainer and a MongoDB consultant.


Subscribe
Connect with
guest
Label
0 Comments

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK