mirror of
https://github.com/MariaDB/server.git
synced 2025-02-17 19:05:37 +01:00
![Sergei Petrunia](/assets/img/avatar_default.png)
Part#1: Frame_n_rows::next_partition() should not assume that the current table->record[0] points to the first row in the partition. Since cursor supports move_to() operation, we dont need this.
686 lines
12 KiB
Text
686 lines
12 KiB
Text
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: Invalid use of group function
|
|
select * from t1 where 1>row_number() over (partition by b order by a);
|
|
ERROR HY000: Invalid use of group function
|
|
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
|
|
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
|
|
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
|
|
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
|
|
drop table t1;
|