mirror of
https://github.com/MariaDB/server.git
synced 2025-08-31 22:22:30 +03:00
" The sort order for the sub-sequence of window functions starting from the element marked by SORTORDER_CHANGE_FLAG up to the next element marked by SORTORDER_CHANGE_FLAG must be taken from the last element of the sub-sequence (not from the first one)."
1770 lines
31 KiB
Plaintext
1770 lines
31 KiB
Plaintext
drop table if exists t1,t2;
|
|
# ########################################################################
|
|
# # Parser tests
|
|
# ########################################################################
|
|
#
|
|
# Check what happens when one attempts to use window function without OVER clause
|
|
create table t1 (a int, b int);
|
|
insert into t1 values (1,1),(2,2);
|
|
select row_number() from t1;
|
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'from t1' at line 1
|
|
select rank() from t1;
|
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'from t1' at line 1
|
|
# Attempt to use window function in the WHERE clause
|
|
select * from t1 where 1=rank() over (order by a);
|
|
ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
|
|
select * from t1 where 1>row_number() over (partition by b order by a);
|
|
ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
|
|
drop table t1;
|
|
# ########################################################################
|
|
# # Functionality tests
|
|
# ########################################################################
|
|
#
|
|
# Check if ROW_NUMBER() works in basic cases
|
|
create table t1(a int, b int, x char(32));
|
|
insert into t1 values (2, 10, 'xx');
|
|
insert into t1 values (2, 10, 'zz');
|
|
insert into t1 values (2, 20, 'yy');
|
|
insert into t1 values (3, 10, 'xxx');
|
|
insert into t1 values (3, 20, 'vvv');
|
|
select a, row_number() over (partition by a order by b) from t1;
|
|
a row_number() over (partition by a order by b)
|
|
2 1
|
|
2 2
|
|
2 3
|
|
3 1
|
|
3 2
|
|
select a, b, x, row_number() over (partition by a order by x) from t1;
|
|
a b x row_number() over (partition by a order by x)
|
|
2 10 xx 1
|
|
2 10 zz 3
|
|
2 20 yy 2
|
|
3 10 xxx 2
|
|
3 20 vvv 1
|
|
drop table t1;
|
|
create table t1 (pk int primary key, a int, b int);
|
|
insert into t1 values
|
|
(1, 10, 22),
|
|
(2, 11, 21),
|
|
(3, 12, 20),
|
|
(4, 13, 19),
|
|
(5, 14, 18);
|
|
select
|
|
pk, a, b,
|
|
row_number() over (order by a),
|
|
row_number() over (order by b)
|
|
from t1;
|
|
pk a b row_number() over (order by a) row_number() over (order by b)
|
|
1 10 22 1 5
|
|
2 11 21 2 4
|
|
3 12 20 3 3
|
|
4 13 19 4 2
|
|
5 14 18 5 1
|
|
drop table t1;
|
|
#
|
|
# Try RANK() function
|
|
#
|
|
create table t2 (
|
|
pk int primary key,
|
|
a int
|
|
);
|
|
insert into t2 values
|
|
( 1 , 0),
|
|
( 2 , 0),
|
|
( 3 , 1),
|
|
( 4 , 1),
|
|
( 8 , 2),
|
|
( 5 , 2),
|
|
( 6 , 2),
|
|
( 7 , 2),
|
|
( 9 , 4),
|
|
(10 , 4);
|
|
select pk, a, rank() over (order by a) from t2;
|
|
pk a rank() over (order by a)
|
|
1 0 1
|
|
2 0 1
|
|
3 1 3
|
|
4 1 3
|
|
8 2 5
|
|
5 2 5
|
|
6 2 5
|
|
7 2 5
|
|
9 4 9
|
|
10 4 9
|
|
select pk, a, rank() over (order by a desc) from t2;
|
|
pk a rank() over (order by a desc)
|
|
1 0 9
|
|
2 0 9
|
|
3 1 7
|
|
4 1 7
|
|
8 2 3
|
|
5 2 3
|
|
6 2 3
|
|
7 2 3
|
|
9 4 1
|
|
10 4 1
|
|
drop table t2;
|
|
#
|
|
# Try DENSE_RANK() function
|
|
#
|
|
create table t3 (
|
|
pk int primary key,
|
|
a int,
|
|
b int
|
|
);
|
|
insert into t3 values
|
|
( 1 , 0, 10),
|
|
( 2 , 0, 10),
|
|
( 3 , 1, 10),
|
|
( 4 , 1, 10),
|
|
( 8 , 2, 10),
|
|
( 5 , 2, 20),
|
|
( 6 , 2, 20),
|
|
( 7 , 2, 20),
|
|
( 9 , 4, 20),
|
|
(10 , 4, 20);
|
|
select pk, a, b, rank() over (order by a), dense_rank() over (order by a) from t3;
|
|
pk a b rank() over (order by a) dense_rank() over (order by a)
|
|
1 0 10 1 1
|
|
2 0 10 1 1
|
|
3 1 10 3 2
|
|
4 1 10 3 2
|
|
8 2 10 5 3
|
|
5 2 20 5 3
|
|
6 2 20 5 3
|
|
7 2 20 5 3
|
|
9 4 20 9 4
|
|
10 4 20 9 4
|
|
select pk, a, b, rank() over (partition by b order by a), dense_rank() over (partition by b order by a) from t3;
|
|
pk a b rank() over (partition by b order by a) dense_rank() over (partition by b order by a)
|
|
1 0 10 1 1
|
|
2 0 10 1 1
|
|
3 1 10 3 2
|
|
4 1 10 3 2
|
|
8 2 10 5 3
|
|
5 2 20 1 1
|
|
6 2 20 1 1
|
|
7 2 20 1 1
|
|
9 4 20 4 2
|
|
10 4 20 4 2
|
|
drop table t3;
|
|
#
|
|
# Try Aggregates as window functions. With frames.
|
|
#
|
|
create table t0 (a int);
|
|
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
|
create table t1 (pk int, c int);
|
|
insert into t1 select a+1,1 from t0;
|
|
update t1 set c=2 where pk not in (1,2,3,4);
|
|
select * from t1;
|
|
pk c
|
|
1 1
|
|
2 1
|
|
3 1
|
|
4 1
|
|
5 2
|
|
6 2
|
|
7 2
|
|
8 2
|
|
9 2
|
|
10 2
|
|
select
|
|
pk, c,
|
|
count(*) over (partition by c order by pk
|
|
rows between 2 preceding and 2 following) as CNT
|
|
from t1;
|
|
pk c CNT
|
|
1 1 3
|
|
2 1 4
|
|
3 1 4
|
|
4 1 3
|
|
5 2 3
|
|
6 2 4
|
|
7 2 5
|
|
8 2 5
|
|
9 2 4
|
|
10 2 3
|
|
select
|
|
pk, c,
|
|
count(*) over (partition by c order by pk
|
|
rows between 1 preceding and 2 following) as CNT
|
|
from t1;
|
|
pk c CNT
|
|
1 1 3
|
|
2 1 4
|
|
3 1 3
|
|
4 1 2
|
|
5 2 3
|
|
6 2 4
|
|
7 2 4
|
|
8 2 4
|
|
9 2 3
|
|
10 2 2
|
|
select
|
|
pk, c,
|
|
count(*) over (partition by c order by pk
|
|
rows between 2 preceding and current row) as CNT
|
|
from t1;
|
|
pk c CNT
|
|
1 1 1
|
|
2 1 2
|
|
3 1 3
|
|
4 1 3
|
|
5 2 1
|
|
6 2 2
|
|
7 2 3
|
|
8 2 3
|
|
9 2 3
|
|
10 2 3
|
|
select
|
|
pk,c,
|
|
count(*) over (partition by c order by pk rows
|
|
between 1 following and 2 following) as CNT
|
|
from t1;
|
|
pk c CNT
|
|
1 1 2
|
|
2 1 2
|
|
3 1 1
|
|
4 1 0
|
|
5 2 2
|
|
6 2 2
|
|
7 2 2
|
|
8 2 2
|
|
9 2 1
|
|
10 2 0
|
|
select
|
|
pk,c,
|
|
count(*) over (partition by c order by pk rows
|
|
between 2 preceding and 1 preceding) as CNT
|
|
from t1;
|
|
pk c CNT
|
|
1 1 0
|
|
2 1 1
|
|
3 1 2
|
|
4 1 2
|
|
5 2 0
|
|
6 2 1
|
|
7 2 2
|
|
8 2 2
|
|
9 2 2
|
|
10 2 2
|
|
select
|
|
pk, c,
|
|
count(*) over (partition by c order by pk
|
|
rows between current row and 1 following) as CNT
|
|
from t1;
|
|
pk c CNT
|
|
1 1 2
|
|
2 1 2
|
|
3 1 2
|
|
4 1 1
|
|
5 2 2
|
|
6 2 2
|
|
7 2 2
|
|
8 2 2
|
|
9 2 2
|
|
10 2 1
|
|
# Check ORDER BY DESC
|
|
select
|
|
pk, c,
|
|
count(*) over (partition by c order by pk desc
|
|
rows between 2 preceding and 2 following) as CNT
|
|
from t1;
|
|
pk c CNT
|
|
1 1 3
|
|
2 1 4
|
|
3 1 4
|
|
4 1 3
|
|
5 2 3
|
|
6 2 4
|
|
7 2 5
|
|
8 2 5
|
|
9 2 4
|
|
10 2 3
|
|
drop table t0,t1;
|
|
#
|
|
# Resolution of window names
|
|
#
|
|
create table t0 (a int);
|
|
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
|
create table t1 (pk int, c int);
|
|
insert into t1 select a+1,1 from t0;
|
|
update t1 set c=2 where pk not in (1,2,3,4);
|
|
select * from t1;
|
|
pk c
|
|
1 1
|
|
2 1
|
|
3 1
|
|
4 1
|
|
5 2
|
|
6 2
|
|
7 2
|
|
8 2
|
|
9 2
|
|
10 2
|
|
select
|
|
pk, c,
|
|
count(*) over w1 as CNT
|
|
from t1
|
|
window w1 as (partition by c order by pk
|
|
rows between 2 preceding and 2 following);
|
|
pk c CNT
|
|
1 1 3
|
|
2 1 4
|
|
3 1 4
|
|
4 1 3
|
|
5 2 3
|
|
6 2 4
|
|
7 2 5
|
|
8 2 5
|
|
9 2 4
|
|
10 2 3
|
|
select
|
|
pk, c,
|
|
count(*) over (w1 rows between 2 preceding and 2 following) as CNT
|
|
from t1
|
|
window w1 as (partition by c order by pk);
|
|
pk c CNT
|
|
1 1 3
|
|
2 1 4
|
|
3 1 4
|
|
4 1 3
|
|
5 2 3
|
|
6 2 4
|
|
7 2 5
|
|
8 2 5
|
|
9 2 4
|
|
10 2 3
|
|
select
|
|
pk, c,
|
|
count(*) over (w1 order by pk rows between 2 preceding and 2 following) as CNT
|
|
from t1
|
|
window w1 as (partition by c);
|
|
pk c CNT
|
|
1 1 3
|
|
2 1 4
|
|
3 1 4
|
|
4 1 3
|
|
5 2 3
|
|
6 2 4
|
|
7 2 5
|
|
8 2 5
|
|
9 2 4
|
|
10 2 3
|
|
select
|
|
pk, c,
|
|
count(*) over (w2 rows between 2 preceding and 2 following) as CNT
|
|
from t1
|
|
window w1 as (partition by c), w2 as (w1 order by pk);
|
|
pk c CNT
|
|
1 1 3
|
|
2 1 4
|
|
3 1 4
|
|
4 1 3
|
|
5 2 3
|
|
6 2 4
|
|
7 2 5
|
|
8 2 5
|
|
9 2 4
|
|
10 2 3
|
|
select
|
|
pk, c,
|
|
count(*) over w3 as CNT
|
|
from t1
|
|
window
|
|
w1 as (partition by c),
|
|
w2 as (w1 order by pk),
|
|
w3 as (w2 rows between 2 preceding and 2 following);
|
|
pk c CNT
|
|
1 1 3
|
|
2 1 4
|
|
3 1 4
|
|
4 1 3
|
|
5 2 3
|
|
6 2 4
|
|
7 2 5
|
|
8 2 5
|
|
9 2 4
|
|
10 2 3
|
|
select
|
|
pk, c,
|
|
count(*) over w as CNT
|
|
from t1
|
|
window w1 as (partition by c order by pk
|
|
rows between 2 preceding and 2 following);
|
|
ERROR HY000: Window specification with name 'w' is not defined
|
|
select
|
|
pk, c,
|
|
count(*) over (w2 rows between 2 preceding and 2 following) as CNT
|
|
from t1
|
|
window w1 as (partition by c), w1 as (order by pk);
|
|
ERROR HY000: Multiple window specifications with the same name 'w1'
|
|
select
|
|
pk, c,
|
|
count(*) over (w2 rows between 2 preceding and 2 following) as CNT
|
|
from t1
|
|
window w1 as (partition by c), w2 as (w partition by c order by pk);
|
|
ERROR HY000: Window specification with name 'w' is not defined
|
|
select
|
|
pk, c,
|
|
count(*) over (w2 rows between 2 preceding and 2 following) as CNT
|
|
from t1
|
|
window w1 as (partition by c), w2 as (w1 partition by c order by pk);
|
|
ERROR HY000: Window specification referencing another one 'w1' cannot contain partition list
|
|
select
|
|
pk, c,
|
|
count(*) over (w2 rows between 2 preceding and 2 following) as CNT
|
|
from t1
|
|
window w1 as (partition by c order by pk), w2 as (w1 order by pk);
|
|
ERROR HY000: Referenced window specification 'w1' already contains order list
|
|
select
|
|
pk, c,
|
|
count(*) over w3 as CNT
|
|
from t1
|
|
window
|
|
w1 as (partition by c),
|
|
w2 as (w1 order by pk rows between 3 preceding and 2 following),
|
|
w3 as (w2 rows between 2 preceding and 2 following);
|
|
ERROR HY000: Referenced window specification 'w2' cannot contain window frame
|
|
select
|
|
pk, c,
|
|
count(*) over w1 as CNT
|
|
from t1
|
|
window w1 as (partition by c order by pk
|
|
rows between unbounded following and 2 following);
|
|
ERROR HY000: Unacceptable combination of window frame bound specifications
|
|
select
|
|
pk, c,
|
|
count(*) over (w1 rows between 2 preceding and unbounded preceding) as CNT
|
|
from t1
|
|
window w1 as (partition by c order by pk);
|
|
ERROR HY000: Unacceptable combination of window frame bound specifications
|
|
select
|
|
pk, c,
|
|
count(*) over (w1 order by pk rows between current row and 2 preceding) as CNT
|
|
from t1
|
|
window w1 as (partition by c);
|
|
ERROR HY000: Unacceptable combination of window frame bound specifications
|
|
select
|
|
pk, c,
|
|
count(*) over (w2 rows between 2 following and current row) as CNT
|
|
from t1
|
|
window w1 as (partition by c), w2 as (w1 order by pk);
|
|
ERROR HY000: Unacceptable combination of window frame bound specifications
|
|
select
|
|
pk, c
|
|
from t1 where rank() over w1 > 2
|
|
window w1 as (partition by c order by pk);
|
|
ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
|
|
select
|
|
c, max(pk) as m
|
|
from t1
|
|
group by c + rank() over w1
|
|
window w1 as (order by m);
|
|
ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
|
|
select
|
|
c, max(pk) as m, rank() over w1 as r
|
|
from t1
|
|
group by c+r
|
|
window w1 as (order by m);
|
|
ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
|
|
select
|
|
c, max(pk) as m, rank() over w1 as r
|
|
from t1
|
|
group by c having c+r > 3
|
|
window w1 as (order by m);
|
|
ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
|
|
select
|
|
c, max(pk) as m, rank() over w1 as r,
|
|
rank() over (partition by r+1 order by m)
|
|
from t1
|
|
group by c
|
|
window w1 as (order by m);
|
|
ERROR HY000: Window function is not allowed in window specification
|
|
select
|
|
c, max(pk) as m, rank() over w1 as r,
|
|
rank() over (partition by m order by r)
|
|
from t1
|
|
group by c
|
|
window w1 as (order by m);
|
|
ERROR HY000: Window function is not allowed in window specification
|
|
select
|
|
c, max(pk) as m, rank() over w1 as r, dense_rank() over w2 as dr
|
|
from t1
|
|
group by c
|
|
window w1 as (order by m), w2 as (partition by r order by m);
|
|
ERROR HY000: Window function is not allowed in window specification
|
|
select
|
|
pk, c,
|
|
row_number() over (partition by c order by pk
|
|
range between unbounded preceding and current row) as r
|
|
from t1;
|
|
ERROR HY000: Window frame is not allowed with 'row_number'
|
|
select
|
|
pk, c,
|
|
rank() over w1 as r
|
|
from t1
|
|
window w1 as (partition by c order by pk
|
|
rows between 2 preceding and 2 following);
|
|
ERROR HY000: Window frame is not allowed with 'rank'
|
|
select
|
|
pk, c,
|
|
dense_rank() over (partition by c order by pk
|
|
rows between 1 preceding and 1 following) as r
|
|
from t1;
|
|
ERROR HY000: Window frame is not allowed with 'dense_rank'
|
|
select
|
|
pk, c,
|
|
rank() over w1 as r
|
|
from t1
|
|
window w1 as (partition by c);
|
|
ERROR HY000: No order list in window specification for 'rank'
|
|
select
|
|
pk, c,
|
|
dense_rank() over (partition by c) as r
|
|
from t1;
|
|
ERROR HY000: No order list in window specification for 'dense_rank'
|
|
drop table t0,t1;
|
|
#
|
|
# MDEV-9634: Window function produces incorrect value
|
|
#
|
|
create table t0 (a int);
|
|
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
|
create table t2 (part_id int, pk int, a int);
|
|
insert into t2 select
|
|
if(a<5, 0, 1), a, if(a<5, NULL, 1) from t0;
|
|
select * from t2;
|
|
part_id pk a
|
|
0 0 NULL
|
|
0 1 NULL
|
|
0 2 NULL
|
|
0 3 NULL
|
|
0 4 NULL
|
|
1 5 1
|
|
1 6 1
|
|
1 7 1
|
|
1 8 1
|
|
1 9 1
|
|
select
|
|
part_id, pk, a,
|
|
count(a) over (partition by part_id order by pk
|
|
rows between 1 preceding and 1 following) as CNT
|
|
from t2;
|
|
part_id pk a CNT
|
|
0 0 NULL 0
|
|
0 1 NULL 0
|
|
0 2 NULL 0
|
|
0 3 NULL 0
|
|
0 4 NULL 0
|
|
1 5 1 2
|
|
1 6 1 3
|
|
1 7 1 3
|
|
1 8 1 3
|
|
1 9 1 2
|
|
drop table t0, t2;
|
|
#
|
|
# RANGE-type bounds
|
|
#
|
|
create table t3 (
|
|
pk int,
|
|
val int
|
|
);
|
|
insert into t3 values
|
|
(0, 1),
|
|
(1, 1),
|
|
(2, 1),
|
|
(3, 2),
|
|
(4, 2),
|
|
(5, 2),
|
|
(6, 2);
|
|
select
|
|
pk,
|
|
val,
|
|
count(val) over (order by val
|
|
range between current row and
|
|
current row)
|
|
as CNT
|
|
from t3;
|
|
pk val CNT
|
|
0 1 3
|
|
1 1 3
|
|
2 1 3
|
|
3 2 4
|
|
4 2 4
|
|
5 2 4
|
|
6 2 4
|
|
insert into t3 values
|
|
(7, 3),
|
|
(8, 3);
|
|
select
|
|
pk,
|
|
val,
|
|
count(val) over (order by val
|
|
range between current row and
|
|
current row)
|
|
as CNT
|
|
from t3;
|
|
pk val CNT
|
|
0 1 3
|
|
1 1 3
|
|
2 1 3
|
|
3 2 4
|
|
4 2 4
|
|
5 2 4
|
|
6 2 4
|
|
7 3 2
|
|
8 3 2
|
|
drop table t3;
|
|
# Now, check with PARTITION BY
|
|
create table t4 (
|
|
part_id int,
|
|
pk int,
|
|
val int
|
|
);
|
|
insert into t4 values
|
|
(1234, 100, 1),
|
|
(1234, 101, 1),
|
|
(1234, 102, 1),
|
|
(1234, 103, 2),
|
|
(1234, 104, 2),
|
|
(1234, 105, 2),
|
|
(1234, 106, 2),
|
|
(1234, 107, 3),
|
|
(1234, 108, 3),
|
|
(5678, 200, 1),
|
|
(5678, 201, 1),
|
|
(5678, 202, 1),
|
|
(5678, 203, 2),
|
|
(5678, 204, 2),
|
|
(5678, 205, 2),
|
|
(5678, 206, 2),
|
|
(5678, 207, 3),
|
|
(5678, 208, 3);
|
|
select
|
|
part_id,
|
|
pk,
|
|
val,
|
|
count(val) over (partition by part_id
|
|
order by val
|
|
range between current row and
|
|
current row)
|
|
as CNT
|
|
from t4;
|
|
part_id pk val CNT
|
|
1234 100 1 3
|
|
1234 101 1 3
|
|
1234 102 1 3
|
|
1234 103 2 4
|
|
1234 104 2 4
|
|
1234 105 2 4
|
|
1234 106 2 4
|
|
1234 107 3 2
|
|
1234 108 3 2
|
|
5678 200 1 3
|
|
5678 201 1 3
|
|
5678 202 1 3
|
|
5678 203 2 4
|
|
5678 204 2 4
|
|
5678 205 2 4
|
|
5678 206 2 4
|
|
5678 207 3 2
|
|
5678 208 3 2
|
|
#
|
|
# Try RANGE UNBOUNDED PRECEDING | FOLLOWING
|
|
#
|
|
select
|
|
part_id,
|
|
pk,
|
|
val,
|
|
count(val) over (partition by part_id
|
|
order by val
|
|
range between unbounded preceding and
|
|
current row)
|
|
as CNT
|
|
from t4;
|
|
part_id pk val CNT
|
|
1234 100 1 3
|
|
1234 101 1 3
|
|
1234 102 1 3
|
|
1234 103 2 7
|
|
1234 104 2 7
|
|
1234 105 2 7
|
|
1234 106 2 7
|
|
1234 107 3 9
|
|
1234 108 3 9
|
|
5678 200 1 3
|
|
5678 201 1 3
|
|
5678 202 1 3
|
|
5678 203 2 7
|
|
5678 204 2 7
|
|
5678 205 2 7
|
|
5678 206 2 7
|
|
5678 207 3 9
|
|
5678 208 3 9
|
|
select
|
|
part_id,
|
|
pk,
|
|
val,
|
|
count(val) over (partition by part_id
|
|
order by val
|
|
range between current row and
|
|
unbounded following)
|
|
as CNT
|
|
from t4;
|
|
part_id pk val CNT
|
|
1234 100 1 9
|
|
1234 101 1 9
|
|
1234 102 1 9
|
|
1234 103 2 6
|
|
1234 104 2 6
|
|
1234 105 2 6
|
|
1234 106 2 6
|
|
1234 107 3 2
|
|
1234 108 3 2
|
|
5678 200 1 9
|
|
5678 201 1 9
|
|
5678 202 1 9
|
|
5678 203 2 6
|
|
5678 204 2 6
|
|
5678 205 2 6
|
|
5678 206 2 6
|
|
5678 207 3 2
|
|
5678 208 3 2
|
|
select
|
|
part_id,
|
|
pk,
|
|
val,
|
|
count(val) over (partition by part_id
|
|
order by val
|
|
range between unbounded preceding and
|
|
unbounded following)
|
|
as CNT
|
|
from t4;
|
|
part_id pk val CNT
|
|
1234 100 1 9
|
|
1234 101 1 9
|
|
1234 102 1 9
|
|
1234 103 2 9
|
|
1234 104 2 9
|
|
1234 105 2 9
|
|
1234 106 2 9
|
|
1234 107 3 9
|
|
1234 108 3 9
|
|
5678 200 1 9
|
|
5678 201 1 9
|
|
5678 202 1 9
|
|
5678 203 2 9
|
|
5678 204 2 9
|
|
5678 205 2 9
|
|
5678 206 2 9
|
|
5678 207 3 9
|
|
5678 208 3 9
|
|
drop table t4;
|
|
#
|
|
# MDEV-9695: Wrong window frame when using RANGE BETWEEN N FOLLOWING AND PRECEDING
|
|
#
|
|
create table t1 (pk int, a int, b int);
|
|
insert into t1 values
|
|
( 1 , 0, 1),
|
|
( 2 , 0, 2),
|
|
( 3 , 1, 4),
|
|
( 4 , 1, 8),
|
|
( 5 , 2, 32),
|
|
( 6 , 2, 64),
|
|
( 7 , 2, 128),
|
|
( 8 , 2, 16);
|
|
select pk, a, b,
|
|
bit_or(b) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) as bit_or
|
|
from t1;
|
|
pk a b bit_or
|
|
1 0 1 3
|
|
2 0 2 3
|
|
3 1 4 12
|
|
4 1 8 12
|
|
5 2 32 96
|
|
6 2 64 224
|
|
7 2 128 208
|
|
8 2 16 144
|
|
# Extra ROWS n PRECEDING tests
|
|
select pk, a, b,
|
|
bit_or(b) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) as bit_or
|
|
from t1;
|
|
pk a b bit_or
|
|
1 0 1 0
|
|
2 0 2 1
|
|
3 1 4 0
|
|
4 1 8 4
|
|
5 2 32 0
|
|
6 2 64 32
|
|
7 2 128 64
|
|
8 2 16 128
|
|
drop table t1;
|
|
create table t2 (
|
|
pk int,
|
|
a int,
|
|
b int
|
|
);
|
|
insert into t2 values
|
|
( 1, 0, 1),
|
|
( 2, 0, 2),
|
|
( 3, 0, 4),
|
|
( 4, 0, 8),
|
|
( 5, 1, 16),
|
|
( 6, 1, 32),
|
|
( 7, 1, 64),
|
|
( 8, 1, 128),
|
|
( 9, 2, 256),
|
|
(10, 2, 512),
|
|
(11, 2, 1024),
|
|
(12, 2, 2048);
|
|
select pk, a, b,
|
|
bit_or(b) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) as bit_or
|
|
from t2;
|
|
pk a b bit_or
|
|
1 0 1 0
|
|
2 0 2 1
|
|
3 0 4 2
|
|
4 0 8 4
|
|
5 1 16 0
|
|
6 1 32 16
|
|
7 1 64 32
|
|
8 1 128 64
|
|
9 2 256 0
|
|
10 2 512 256
|
|
11 2 1024 512
|
|
12 2 2048 1024
|
|
select pk, a, b,
|
|
bit_or(b) over (partition by a order by pk ROWS BETWEEN 2 PRECEDING AND 2 PRECEDING) as bit_or
|
|
from t2;
|
|
pk a b bit_or
|
|
1 0 1 0
|
|
2 0 2 0
|
|
3 0 4 1
|
|
4 0 8 2
|
|
5 1 16 0
|
|
6 1 32 0
|
|
7 1 64 16
|
|
8 1 128 32
|
|
9 2 256 0
|
|
10 2 512 0
|
|
11 2 1024 256
|
|
12 2 2048 512
|
|
select pk, a, b,
|
|
bit_or(b) over (partition by a order by pk ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING) as bit_or
|
|
from t2;
|
|
pk a b bit_or
|
|
1 0 1 0
|
|
2 0 2 1
|
|
3 0 4 3
|
|
4 0 8 6
|
|
5 1 16 0
|
|
6 1 32 16
|
|
7 1 64 48
|
|
8 1 128 96
|
|
9 2 256 0
|
|
10 2 512 256
|
|
11 2 1024 768
|
|
12 2 2048 1536
|
|
# Check CURRENT ROW
|
|
select pk, a, b,
|
|
bit_or(b) over (partition by a order by pk ROWS BETWEEN CURRENT ROW AND CURRENT ROW) as bit_or
|
|
from t2;
|
|
pk a b bit_or
|
|
1 0 1 1
|
|
2 0 2 2
|
|
3 0 4 4
|
|
4 0 8 8
|
|
5 1 16 16
|
|
6 1 32 32
|
|
7 1 64 64
|
|
8 1 128 128
|
|
9 2 256 256
|
|
10 2 512 512
|
|
11 2 1024 1024
|
|
12 2 2048 2048
|
|
drop table t2;
|
|
#
|
|
# Try RANGE PRECEDING|FOLLWING n
|
|
#
|
|
create table t1 (
|
|
part_id int,
|
|
pk int,
|
|
a int
|
|
);
|
|
insert into t1 values
|
|
(10, 1, 1),
|
|
(10, 2, 2),
|
|
(10, 3, 4),
|
|
(10, 4, 8),
|
|
(10, 5,26),
|
|
(10, 6,27),
|
|
(10, 7,40),
|
|
(10, 8,71),
|
|
(10, 9,72);
|
|
select
|
|
pk, a,
|
|
count(a) over (ORDER BY a
|
|
RANGE BETWEEN UNBOUNDED PRECEDING
|
|
AND 10 FOLLOWING) as cnt
|
|
from t1;
|
|
pk a cnt
|
|
1 1 4
|
|
2 2 4
|
|
3 4 4
|
|
4 8 4
|
|
5 26 6
|
|
6 27 6
|
|
7 40 7
|
|
8 71 9
|
|
9 72 9
|
|
select
|
|
pk, a,
|
|
count(a) over (ORDER BY a DESC
|
|
RANGE BETWEEN UNBOUNDED PRECEDING
|
|
AND 10 FOLLOWING) as cnt
|
|
from t1;
|
|
pk a cnt
|
|
1 1 9
|
|
2 2 9
|
|
3 4 9
|
|
4 8 9
|
|
5 26 5
|
|
6 27 5
|
|
7 40 3
|
|
8 71 2
|
|
9 72 2
|
|
select
|
|
pk, a,
|
|
count(a) over (ORDER BY a
|
|
RANGE BETWEEN UNBOUNDED PRECEDING
|
|
AND 1 FOLLOWING) as cnt
|
|
from t1;
|
|
pk a cnt
|
|
1 1 2
|
|
2 2 2
|
|
3 4 3
|
|
4 8 4
|
|
5 26 6
|
|
6 27 6
|
|
7 40 7
|
|
8 71 9
|
|
9 72 9
|
|
select
|
|
pk, a,
|
|
count(a) over (ORDER BY a
|
|
RANGE BETWEEN UNBOUNDED PRECEDING
|
|
AND 10 PRECEDING) as cnt
|
|
from t1;
|
|
pk a cnt
|
|
1 1 0
|
|
2 2 0
|
|
3 4 0
|
|
4 8 0
|
|
5 26 4
|
|
6 27 4
|
|
7 40 6
|
|
8 71 7
|
|
9 72 7
|
|
select
|
|
pk, a,
|
|
count(a) over (ORDER BY a DESC
|
|
RANGE BETWEEN UNBOUNDED PRECEDING
|
|
AND 10 PRECEDING) as cnt
|
|
from t1;
|
|
pk a cnt
|
|
1 1 5
|
|
2 2 5
|
|
3 4 5
|
|
4 8 5
|
|
5 26 3
|
|
6 27 3
|
|
7 40 2
|
|
8 71 0
|
|
9 72 0
|
|
select
|
|
pk, a,
|
|
count(a) over (ORDER BY a
|
|
RANGE BETWEEN UNBOUNDED PRECEDING
|
|
AND 1 PRECEDING) as cnt
|
|
from t1;
|
|
pk a cnt
|
|
1 1 0
|
|
2 2 1
|
|
3 4 2
|
|
4 8 3
|
|
5 26 4
|
|
6 27 5
|
|
7 40 6
|
|
8 71 7
|
|
9 72 8
|
|
select
|
|
pk, a,
|
|
count(a) over (ORDER BY a
|
|
RANGE BETWEEN 1 PRECEDING
|
|
AND CURRENT ROW) as cnt
|
|
from t1;
|
|
pk a cnt
|
|
1 1 1
|
|
2 2 2
|
|
3 4 1
|
|
4 8 1
|
|
5 26 1
|
|
6 27 2
|
|
7 40 1
|
|
8 71 1
|
|
9 72 2
|
|
select
|
|
pk, a,
|
|
count(a) over (ORDER BY a DESC
|
|
RANGE BETWEEN 1 PRECEDING
|
|
AND CURRENT ROW) as cnt
|
|
from t1;
|
|
pk a cnt
|
|
1 1 2
|
|
2 2 1
|
|
3 4 1
|
|
4 8 1
|
|
5 26 2
|
|
6 27 1
|
|
7 40 1
|
|
8 71 2
|
|
9 72 1
|
|
select
|
|
pk, a,
|
|
count(a) over (ORDER BY a
|
|
RANGE BETWEEN 1 FOLLOWING
|
|
AND 3 FOLLOWING) as cnt
|
|
from t1;
|
|
pk a cnt
|
|
1 1 2
|
|
2 2 1
|
|
3 4 0
|
|
4 8 0
|
|
5 26 1
|
|
6 27 0
|
|
7 40 0
|
|
8 71 1
|
|
9 72 0
|
|
# Try CURRENT ROW with[out] DESC
|
|
select
|
|
pk, a,
|
|
count(a) over (ORDER BY a
|
|
RANGE BETWEEN CURRENT ROW
|
|
AND 1 FOLLOWING) as cnt
|
|
from t1;
|
|
pk a cnt
|
|
1 1 2
|
|
2 2 1
|
|
3 4 1
|
|
4 8 1
|
|
5 26 2
|
|
6 27 1
|
|
7 40 1
|
|
8 71 2
|
|
9 72 1
|
|
select
|
|
pk, a,
|
|
count(a) over (order by a desc
|
|
range between current row
|
|
and 1 following) as cnt
|
|
from t1;
|
|
pk a cnt
|
|
1 1 1
|
|
2 2 2
|
|
3 4 1
|
|
4 8 1
|
|
5 26 1
|
|
6 27 2
|
|
7 40 1
|
|
8 71 1
|
|
9 72 2
|
|
insert into t1 select 22, pk, a from t1;
|
|
select
|
|
part_id, pk, a,
|
|
count(a) over (PARTITION BY part_id
|
|
ORDER BY a
|
|
RANGE BETWEEN UNBOUNDED PRECEDING
|
|
AND 10 FOLLOWING) as cnt
|
|
from t1;
|
|
part_id pk a cnt
|
|
10 1 1 4
|
|
10 2 2 4
|
|
10 3 4 4
|
|
10 4 8 4
|
|
10 5 26 6
|
|
10 6 27 6
|
|
10 7 40 7
|
|
10 8 71 9
|
|
10 9 72 9
|
|
22 1 1 4
|
|
22 2 2 4
|
|
22 3 4 4
|
|
22 4 8 4
|
|
22 5 26 6
|
|
22 6 27 6
|
|
22 7 40 7
|
|
22 8 71 9
|
|
22 9 72 9
|
|
select
|
|
pk, a,
|
|
count(a) over (PARTITION BY part_id
|
|
ORDER BY a
|
|
RANGE BETWEEN UNBOUNDED PRECEDING
|
|
AND 1 PRECEDING) as cnt
|
|
from t1;
|
|
pk a cnt
|
|
1 1 0
|
|
2 2 1
|
|
3 4 2
|
|
4 8 3
|
|
5 26 4
|
|
6 27 5
|
|
7 40 6
|
|
8 71 7
|
|
9 72 8
|
|
1 1 0
|
|
2 2 1
|
|
3 4 2
|
|
4 8 3
|
|
5 26 4
|
|
6 27 5
|
|
7 40 6
|
|
8 71 7
|
|
9 72 8
|
|
drop table t1;
|
|
# Try a RANGE frame over non-integer datatype:
|
|
create table t1 (
|
|
col1 int,
|
|
a decimal(5,3)
|
|
);
|
|
insert into t1 values (1, 0.45);
|
|
insert into t1 values (1, 0.5);
|
|
insert into t1 values (1, 0.55);
|
|
insert into t1 values (1, 1.21);
|
|
insert into t1 values (1, 1.22);
|
|
insert into t1 values (1, 3.33);
|
|
select
|
|
a,
|
|
count(col1) over (order by a
|
|
range between 0.1 preceding
|
|
and 0.1 following)
|
|
from t1;
|
|
a count(col1) over (order by a
|
|
range between 0.1 preceding
|
|
and 0.1 following)
|
|
0.450 3
|
|
0.500 3
|
|
0.550 3
|
|
1.210 2
|
|
1.220 2
|
|
3.330 1
|
|
drop table t1;
|
|
#
|
|
# RANGE-type frames and NULL values
|
|
#
|
|
create table t1 (
|
|
pk int,
|
|
a int,
|
|
b int
|
|
);
|
|
insert into t1 values (1, NULL,1);
|
|
insert into t1 values (2, NULL,1);
|
|
insert into t1 values (3, NULL,1);
|
|
insert into t1 values (4, 10 ,1);
|
|
insert into t1 values (5, 11 ,1);
|
|
insert into t1 values (6, 12 ,1);
|
|
insert into t1 values (7, 13 ,1);
|
|
insert into t1 values (8, 14 ,1);
|
|
select
|
|
pk, a,
|
|
count(b) over (order by a
|
|
range between 2 preceding
|
|
and 2 following) as CNT
|
|
from t1;
|
|
pk a CNT
|
|
1 NULL 3
|
|
2 NULL 3
|
|
3 NULL 3
|
|
4 10 3
|
|
5 11 4
|
|
6 12 5
|
|
7 13 4
|
|
8 14 3
|
|
drop table t1;
|
|
#
|
|
# Try ranges that have bound1 > bound2. The standard actually allows them
|
|
#
|
|
create table t0 (a int);
|
|
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
|
create table t1 (pk int, c int);
|
|
insert into t1 select a+1,1 from t0;
|
|
update t1 set c=2 where pk not in (1,2,3,4);
|
|
select * from t1;
|
|
pk c
|
|
1 1
|
|
2 1
|
|
3 1
|
|
4 1
|
|
5 2
|
|
6 2
|
|
7 2
|
|
8 2
|
|
9 2
|
|
10 2
|
|
select
|
|
pk, c,
|
|
count(*) over (partition by c
|
|
order by pk
|
|
rows between 1 preceding
|
|
and 2 preceding)
|
|
as cnt
|
|
from t1;
|
|
pk c cnt
|
|
1 1 0
|
|
2 1 0
|
|
3 1 0
|
|
4 1 0
|
|
5 2 0
|
|
6 2 0
|
|
7 2 0
|
|
8 2 0
|
|
9 2 0
|
|
10 2 0
|
|
select
|
|
pk, c,
|
|
count(*) over (partition by c
|
|
order by pk
|
|
range between 1 preceding
|
|
and 2 preceding)
|
|
as cnt
|
|
from t1;
|
|
pk c cnt
|
|
1 1 0
|
|
2 1 0
|
|
3 1 0
|
|
4 1 0
|
|
5 2 0
|
|
6 2 0
|
|
7 2 0
|
|
8 2 0
|
|
9 2 0
|
|
10 2 0
|
|
drop table t0, t1;
|
|
#
|
|
# Error checking for frame bounds
|
|
#
|
|
create table t1 (a int, b int, c varchar(32));
|
|
insert into t1 values (1,1,'foo');
|
|
insert into t1 values (2,2,'bar');
|
|
select
|
|
count(*) over (order by a,b
|
|
range between unbounded preceding and current row)
|
|
from t1;
|
|
ERROR HY000: RANGE-type frame requires ORDER BY clause with single sort key
|
|
select
|
|
count(*) over (order by c
|
|
range between unbounded preceding and current row)
|
|
from t1;
|
|
ERROR HY000: Numeric datatype is required for RANGE-type frame
|
|
select
|
|
count(*) over (order by a
|
|
range between 'abcd' preceding and current row)
|
|
from t1;
|
|
ERROR HY000: Numeric datatype is required for RANGE-type frame
|
|
select
|
|
count(*) over (order by a
|
|
range between current row and 'foo' following)
|
|
from t1;
|
|
ERROR HY000: Numeric datatype is required for RANGE-type frame
|
|
# Try range frame with invalid bounds
|
|
select
|
|
count(*) over (order by a
|
|
rows between 0.5 preceding and current row)
|
|
from t1;
|
|
ERROR HY000: Integer is required for ROWS-type frame
|
|
select
|
|
count(*) over (order by a
|
|
rows between current row and 3.14 following)
|
|
from t1;
|
|
ERROR HY000: Integer is required for ROWS-type frame
|
|
#
|
|
# EXCLUDE clause is parsed but not supported
|
|
#
|
|
select
|
|
count(*) over (order by a
|
|
rows between 1 preceding and 1 following
|
|
exclude current row)
|
|
from t1;
|
|
ERROR HY000: Frame exclusion is not supported yet
|
|
select
|
|
count(*) over (order by a
|
|
range between 1 preceding and 1 following
|
|
exclude ties)
|
|
from t1;
|
|
ERROR HY000: Frame exclusion is not supported yet
|
|
select
|
|
count(*) over (order by a
|
|
range between 1 preceding and 1 following
|
|
exclude group)
|
|
from t1;
|
|
ERROR HY000: Frame exclusion is not supported yet
|
|
select
|
|
count(*) over (order by a
|
|
rows between 1 preceding and 1 following
|
|
exclude no others)
|
|
from t1;
|
|
count(*) over (order by a
|
|
rows between 1 preceding and 1 following
|
|
exclude no others)
|
|
2
|
|
2
|
|
drop table t1;
|
|
#
|
|
# Window function in grouping query
|
|
#
|
|
create table t1 (
|
|
username varchar(32),
|
|
amount int
|
|
);
|
|
insert into t1 values
|
|
('user1',1),
|
|
('user1',5),
|
|
('user1',3),
|
|
('user2',10),
|
|
('user2',20),
|
|
('user2',30);
|
|
select
|
|
username,
|
|
sum(amount) as s,
|
|
rank() over (order by s desc)
|
|
from t1
|
|
group by username;
|
|
username s rank() over (order by s desc)
|
|
user1 9 2
|
|
user2 60 1
|
|
drop table t1;
|
|
#
|
|
# mdev-9719: Window function in prepared statement
|
|
#
|
|
create table t1(a int, b int, x char(32));
|
|
insert into t1 values (2, 10, 'xx');
|
|
insert into t1 values (2, 10, 'zz');
|
|
insert into t1 values (2, 20, 'yy');
|
|
insert into t1 values (3, 10, 'xxx');
|
|
insert into t1 values (3, 20, 'vvv');
|
|
prepare stmt from 'select a, row_number() over (partition by a order by b) from t1';
|
|
execute stmt;
|
|
a row_number() over (partition by a order by b)
|
|
2 1
|
|
2 2
|
|
2 3
|
|
3 1
|
|
3 2
|
|
drop table t1;
|
|
#
|
|
# mdev-9754: Window name resolution in prepared statement
|
|
#
|
|
create table t0 (a int);
|
|
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
|
create table t1 (pk int, c int);
|
|
insert into t1 select a+1,1 from t0;
|
|
update t1 set c=2 where pk not in (1,2,3,4);
|
|
select * from t1;
|
|
pk c
|
|
1 1
|
|
2 1
|
|
3 1
|
|
4 1
|
|
5 2
|
|
6 2
|
|
7 2
|
|
8 2
|
|
9 2
|
|
10 2
|
|
prepare stmt from
|
|
'select
|
|
pk, c,
|
|
count(*) over w1 as CNT
|
|
from t1
|
|
window w1 as (partition by c order by pk
|
|
rows between 2 preceding and 2 following)';
|
|
execute stmt;
|
|
pk c CNT
|
|
1 1 3
|
|
2 1 4
|
|
3 1 4
|
|
4 1 3
|
|
5 2 3
|
|
6 2 4
|
|
7 2 5
|
|
8 2 5
|
|
9 2 4
|
|
10 2 3
|
|
drop table t0,t1;
|
|
#
|
|
# EXPLAIN FORMAT=JSON support for window functions
|
|
#
|
|
create table t0 (a int);
|
|
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
|
explain format=json select rank() over (order by a) from t0;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"window_functions_computation": {
|
|
"sorts": {
|
|
"filesort": {
|
|
"sort_key": "t0.a"
|
|
}
|
|
},
|
|
"temporary_table": {
|
|
"table": {
|
|
"table_name": "t0",
|
|
"access_type": "ALL",
|
|
"rows": 10,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
create table t1 (a int, b int, c int);
|
|
insert into t1 select a,a,a from t0;
|
|
explain format=json
|
|
select
|
|
a,
|
|
rank() over (order by sum(b))
|
|
from t1
|
|
group by a;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"filesort": {
|
|
"sort_key": "t1.a",
|
|
"window_functions_computation": {
|
|
"sorts": {
|
|
"filesort": {
|
|
"sort_key": "sum(t1.b)"
|
|
}
|
|
},
|
|
"temporary_table": {
|
|
"table": {
|
|
"table_name": "t1",
|
|
"access_type": "ALL",
|
|
"rows": 10,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
explain format=json
|
|
select
|
|
a,
|
|
rank() over (order by sum(b))
|
|
from t1
|
|
group by a
|
|
order by null;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"window_functions_computation": {
|
|
"sorts": {
|
|
"filesort": {
|
|
"sort_key": "sum(t1.b)"
|
|
}
|
|
},
|
|
"temporary_table": {
|
|
"table": {
|
|
"table_name": "t1",
|
|
"access_type": "ALL",
|
|
"rows": 10,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#
|
|
# Check how window function works together with GROUP BY and HAVING
|
|
#
|
|
select b,max(a) as MX, rank() over (order by b) from t1 group by b having MX in (3,5,7);
|
|
b MX rank() over (order by b)
|
|
3 3 1
|
|
5 5 2
|
|
7 7 3
|
|
explain format=json
|
|
select b,max(a) as MX, rank() over (order by b) from t1 group by b having MX in (3,5,7);
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"having_condition": "(MX in (3,5,7))",
|
|
"filesort": {
|
|
"sort_key": "t1.b",
|
|
"window_functions_computation": {
|
|
"sorts": {
|
|
"filesort": {
|
|
"sort_key": "t1.b"
|
|
}
|
|
},
|
|
"temporary_table": {
|
|
"table": {
|
|
"table_name": "t1",
|
|
"access_type": "ALL",
|
|
"rows": 10,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
drop table t1;
|
|
drop table t0;
|
|
#
|
|
# Building ordering index for window functions
|
|
#
|
|
create table t1 (
|
|
pk int primary key,
|
|
a int,
|
|
b int,
|
|
c int
|
|
);
|
|
insert into t1 values
|
|
(101 , 0, 10, 1),
|
|
(102 , 0, 10, 2),
|
|
(103 , 1, 10, 3),
|
|
(104 , 1, 10, 4),
|
|
(108 , 2, 10, 5),
|
|
(105 , 2, 20, 6),
|
|
(106 , 2, 20, 7),
|
|
(107 , 2, 20, 8),
|
|
(109 , 4, 20, 9),
|
|
(110 , 4, 20, 10),
|
|
(111 , 5, NULL, 11),
|
|
(112 , 5, 1, 12),
|
|
(113 , 5, NULL, 13),
|
|
(114 , 5, NULL, 14),
|
|
(115 , 5, NULL, 15),
|
|
(116 , 6, 1, NULL),
|
|
(117 , 6, 1, 10),
|
|
(118 , 6, 1, 1),
|
|
(119 , 6, 1, NULL),
|
|
(120 , 6, 1, NULL),
|
|
(121 , 6, 1, NULL),
|
|
(122 , 6, 1, 2),
|
|
(123 , 6, 1, 20),
|
|
(124 , 6, 1, -10),
|
|
(125 , 6, 1, NULL),
|
|
(126 , 6, 1, NULL),
|
|
(127 , 6, 1, NULL);
|
|
select sum(b) over (partition by a order by b,pk
|
|
rows between unbounded preceding and current row) as c1,
|
|
avg(b) over (w1 rows between 1 preceding and 1 following) as c2,
|
|
sum(c) over (w2 rows between 1 preceding and 1 following) as c5,
|
|
avg(b) over (w1 rows between 5 preceding and 5 following) as c3,
|
|
sum(b) over (w1 rows between 1 preceding and 1 following) as c4
|
|
from t1
|
|
window w1 as (partition by a order by b,pk),
|
|
w2 as (partition by b order by c,pk);
|
|
c1 c2 c5 c3 c4
|
|
1 1.0000 42 1.0000 1
|
|
1 1.0000 NULL 1.0000 2
|
|
10 1.0000 NULL 1.0000 3
|
|
10 10.0000 3 10.0000 20
|
|
10 10.0000 9 10.0000 20
|
|
10 15.0000 9 17.5000 30
|
|
11 1.0000 NULL 1.0000 3
|
|
12 1.0000 -10 1.0000 2
|
|
2 1.0000 24 1.0000 3
|
|
20 10.0000 12 10.0000 20
|
|
20 10.0000 6 10.0000 20
|
|
20 20.0000 27 20.0000 40
|
|
3 1.0000 -7 1.0000 3
|
|
30 16.6667 13 17.5000 50
|
|
4 1.0000 NULL 1.0000 3
|
|
40 20.0000 19 20.0000 40
|
|
5 1.0000 NULL 1.0000 3
|
|
50 20.0000 21 17.5000 60
|
|
6 1.0000 NULL 1.0000 3
|
|
7 1.0000 13 1.0000 3
|
|
70 20.0000 24 17.5000 40
|
|
8 1.0000 32 1.0000 3
|
|
9 1.0000 -9 1.0000 3
|
|
NULL 1.0000 29 1.0000 1
|
|
NULL NULL 24 1.0000 NULL
|
|
NULL NULL 38 1.0000 NULL
|
|
NULL NULL 42 1.0000 NULL
|
|
drop table t1;
|
|
#
|
|
# MDEV-9848: Window functions: reuse sorting and/or scanning
|
|
#
|
|
create table t1 (a int, b int, c int);
|
|
insert into t1 values
|
|
(1,3,1),
|
|
(2,2,1),
|
|
(3,1,1);
|
|
# Check using counters
|
|
flush status;
|
|
select
|
|
rank() over (partition by c order by a),
|
|
rank() over (partition by c order by b)
|
|
from t1;
|
|
rank() over (partition by c order by a) rank() over (partition by c order by b)
|
|
1 3
|
|
2 2
|
|
3 1
|
|
show status like '%sort%';
|
|
Variable_name Value
|
|
Sort_merge_passes 0
|
|
Sort_priority_queue_sorts 0
|
|
Sort_range 0
|
|
Sort_rows 6
|
|
Sort_scan 2
|
|
flush status;
|
|
select
|
|
rank() over (partition by c order by a),
|
|
rank() over (partition by c order by a)
|
|
from t1;
|
|
rank() over (partition by c order by a) rank() over (partition by c order by a)
|
|
1 1
|
|
2 2
|
|
3 3
|
|
show status like '%sort%';
|
|
Variable_name Value
|
|
Sort_merge_passes 0
|
|
Sort_priority_queue_sorts 0
|
|
Sort_range 0
|
|
Sort_rows 3
|
|
Sort_scan 1
|
|
explain format=json
|
|
select
|
|
rank() over (partition by c order by a),
|
|
rank() over (partition by c order by a)
|
|
from t1;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"window_functions_computation": {
|
|
"sorts": {
|
|
"filesort": {
|
|
"sort_key": "t1.c, t1.a"
|
|
}
|
|
},
|
|
"temporary_table": {
|
|
"table": {
|
|
"table_name": "t1",
|
|
"access_type": "ALL",
|
|
"rows": 3,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
explain format=json
|
|
select
|
|
rank() over (order by a),
|
|
row_number() over (order by a)
|
|
from t1;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"window_functions_computation": {
|
|
"sorts": {
|
|
"filesort": {
|
|
"sort_key": "t1.a"
|
|
}
|
|
},
|
|
"temporary_table": {
|
|
"table": {
|
|
"table_name": "t1",
|
|
"access_type": "ALL",
|
|
"rows": 3,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
explain format=json
|
|
select
|
|
rank() over (partition by c order by a),
|
|
count(*) over (partition by c)
|
|
from t1;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"window_functions_computation": {
|
|
"sorts": {
|
|
"filesort": {
|
|
"sort_key": "t1.c, t1.a"
|
|
}
|
|
},
|
|
"temporary_table": {
|
|
"table": {
|
|
"table_name": "t1",
|
|
"access_type": "ALL",
|
|
"rows": 3,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
explain format=json
|
|
select
|
|
count(*) over (partition by c),
|
|
rank() over (partition by c order by a)
|
|
from t1;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"window_functions_computation": {
|
|
"sorts": {
|
|
"filesort": {
|
|
"sort_key": "t1.c, t1.a"
|
|
}
|
|
},
|
|
"temporary_table": {
|
|
"table": {
|
|
"table_name": "t1",
|
|
"access_type": "ALL",
|
|
"rows": 3,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
drop table t1;
|
|
#
|
|
# MDEV-9847: Window functions: crash with big_tables=1
|
|
#
|
|
create table t1(a int);
|
|
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
|
set @tmp=@@big_tables;
|
|
set big_tables=1;
|
|
select rank() over (order by a) from t1;
|
|
rank() over (order by a)
|
|
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
6
|
|
7
|
|
8
|
|
9
|
|
10
|
|
set big_tables=@tmp;
|
|
drop table t1;
|