mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 04:22:27 +01:00
957809b190
When join output is just one row, we still need to compute window function values for it. We could skip invoking filesort for it, but it doesn't seem to be worth it to do such optimization.
1961 lines
35 KiB
Text
1961 lines
35 KiB
Text
drop table if exists t1,t2;
|
|
drop view if exists v1;
|
|
# ########################################################################
|
|
# # 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 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;
|
|
#
|
|
# Check if "ORDER BY window_func" works
|
|
#
|
|
create table t1 (s1 int, s2 char(5));
|
|
insert into t1 values (1,'a');
|
|
insert into t1 values (null,null);
|
|
insert into t1 values (1,null);
|
|
insert into t1 values (null,'a');
|
|
insert into t1 values (2,'b');
|
|
insert into t1 values (-1,'');
|
|
explain format=json
|
|
select *, row_number() over (order by s1, s2) as X from t1 order by X desc;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"filesort": {
|
|
"sort_key": "X",
|
|
"window_functions_computation": {
|
|
"sorts": {
|
|
"filesort": {
|
|
"sort_key": "t1.s1, t1.s2"
|
|
}
|
|
},
|
|
"temporary_table": {
|
|
"table": {
|
|
"table_name": "t1",
|
|
"access_type": "ALL",
|
|
"rows": 6,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
select *, row_number() over (order by s1, s2) as X from t1 order by X desc;
|
|
s1 s2 X
|
|
2 b 6
|
|
1 a 5
|
|
1 NULL 4
|
|
-1 3
|
|
NULL a 2
|
|
NULL NULL 1
|
|
drop table t1;
|
|
#
|
|
# Try window functions that are not directly present in the select list
|
|
#
|
|
create table t1 (a int, b int);
|
|
insert into t1 values
|
|
(1,3),
|
|
(2,2),
|
|
(3,1);
|
|
select
|
|
rank() over (order by a) -
|
|
rank() over (order by b)
|
|
from
|
|
t1;
|
|
rank() over (order by a) -
|
|
rank() over (order by b)
|
|
0
|
|
0
|
|
0
|
|
drop table t1;
|
|
#
|
|
# MDEV-9894: Assertion `0' failed in Window_func_runner::setup
|
|
# return ER_NOT_SUPPORTED_YET for aggregates that are not yet supported
|
|
# as window functions.
|
|
#
|
|
create table t1 (i int);
|
|
insert into t1 values (1),(2);
|
|
SELECT MAX(i) OVER (PARTITION BY (i)) FROM t1;
|
|
ERROR 42000: This version of MariaDB doesn't yet support 'This aggregate as window function'
|
|
drop table t1;
|
|
#
|
|
# Check the 0 in ROWS 0 PRECEDING
|
|
#
|
|
create table t1 (
|
|
part_id int,
|
|
pk int,
|
|
a int
|
|
);
|
|
insert into t1 values (1, 1, 1);
|
|
insert into t1 values (1, 2, 2);
|
|
insert into t1 values (1, 3, 4);
|
|
insert into t1 values (1, 4, 8);
|
|
select
|
|
pk, a,
|
|
sum(a) over (order by pk rows between 0 preceding and current row)
|
|
from t1;
|
|
pk a sum(a) over (order by pk rows between 0 preceding and current row)
|
|
1 1 1
|
|
2 2 2
|
|
3 4 4
|
|
4 8 8
|
|
select
|
|
pk, a,
|
|
sum(a) over (order by pk rows between 1 preceding and 0 preceding)
|
|
from t1;
|
|
pk a sum(a) over (order by pk rows between 1 preceding and 0 preceding)
|
|
1 1 1
|
|
2 2 3
|
|
3 4 6
|
|
4 8 12
|
|
insert into t1 values (200, 1, 1);
|
|
insert into t1 values (200, 2, 2);
|
|
insert into t1 values (200, 3, 4);
|
|
insert into t1 values (200, 4, 8);
|
|
select
|
|
part_id, pk, a,
|
|
sum(a) over (partition by part_id order by pk rows between 0 preceding and current row)
|
|
from t1;
|
|
part_id pk a sum(a) over (partition by part_id order by pk rows between 0 preceding and current row)
|
|
1 1 1 1
|
|
1 2 2 2
|
|
1 3 4 4
|
|
1 4 8 8
|
|
200 1 1 1
|
|
200 2 2 2
|
|
200 3 4 4
|
|
200 4 8 8
|
|
select
|
|
part_id, pk, a,
|
|
sum(a) over (partition by part_id order by pk rows between 1 preceding and 0 preceding)
|
|
from t1;
|
|
part_id pk a sum(a) over (partition by part_id order by pk rows between 1 preceding and 0 preceding)
|
|
1 1 1 1
|
|
1 2 2 3
|
|
1 3 4 6
|
|
1 4 8 12
|
|
200 1 1 1
|
|
200 2 2 3
|
|
200 3 4 6
|
|
200 4 8 12
|
|
drop table t1;
|
|
#
|
|
# MDEV-9780, The "DISTINCT must not bet converted into GROUP BY when
|
|
# window functions are present" part
|
|
#
|
|
create table t1 (part_id int, a int);
|
|
insert into t1 values
|
|
(100, 1),
|
|
(100, 2),
|
|
(100, 2),
|
|
(100, 3),
|
|
(2000, 1),
|
|
(2000, 2),
|
|
(2000, 3),
|
|
(2000, 3),
|
|
(2000, 3);
|
|
select rank() over (partition by part_id order by a) from t1;
|
|
rank() over (partition by part_id order by a)
|
|
1
|
|
2
|
|
2
|
|
4
|
|
1
|
|
2
|
|
3
|
|
3
|
|
3
|
|
select distinct rank() over (partition by part_id order by a) from t1;
|
|
rank() over (partition by part_id order by a)
|
|
1
|
|
2
|
|
4
|
|
3
|
|
explain format=json
|
|
select distinct rank() over (partition by part_id order by a) from t1;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"duplicate_removal": {
|
|
"window_functions_computation": {
|
|
"sorts": {
|
|
"filesort": {
|
|
"sort_key": "t1.part_id, t1.a"
|
|
}
|
|
},
|
|
"temporary_table": {
|
|
"table": {
|
|
"table_name": "t1",
|
|
"access_type": "ALL",
|
|
"rows": 9,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
drop table t1;
|
|
#
|
|
# MDEV-9893: Window functions with different ORDER BY lists,
|
|
# one of these lists containing an expression
|
|
#
|
|
create table t1 (s1 int, s2 char(5));
|
|
insert into t1 values (1,'a');
|
|
insert into t1 values (null,null);
|
|
insert into t1 values (3,null);
|
|
insert into t1 values (4,'a');
|
|
insert into t1 values (2,'b');
|
|
insert into t1 values (-1,'');
|
|
select
|
|
*,
|
|
ROW_NUMBER() OVER (order by s1),
|
|
CUME_DIST() OVER (order by -s1)
|
|
from t1;
|
|
s1 s2 ROW_NUMBER() OVER (order by s1) CUME_DIST() OVER (order by -s1)
|
|
1 a 3 0.8333333333
|
|
NULL NULL 1 0.1666666667
|
|
3 NULL 5 0.5000000000
|
|
4 a 6 0.3333333333
|
|
2 b 4 0.6666666667
|
|
-1 2 1.0000000000
|
|
drop table t1;
|
|
#
|
|
# MDEV-9925: Wrong result with aggregate function as a window function
|
|
#
|
|
create table t1 (i int);
|
|
insert into t1 values (1),(2);
|
|
select i, sum(i) over (partition by i) from t1;
|
|
i sum(i) over (partition by i)
|
|
1 1
|
|
2 2
|
|
drop table t1;
|
|
#
|
|
# MDEV-9922: Assertion `!join->only_const_tables() && fsort' failed in int create_sort_index
|
|
#
|
|
create view v1 as select 1 as i;
|
|
select rank() over (order by i) from v1;
|
|
rank() over (order by i)
|
|
1
|
|
drop view v1;
|