2016-02-05 14:24:35 +03:00
drop table if exists t1,t2;
2016-02-07 01:06:56 +03:00
# ########################################################################
# # Parser tests
# ########################################################################
2016-02-06 01:53:17 +03:00
#
# 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
2016-02-07 01:06:56 +03:00
# 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
2016-02-06 01:53:17 +03:00
drop table t1;
2016-02-07 01:06:56 +03:00
# ########################################################################
# # Functionality tests
# ########################################################################
2016-02-06 01:53:17 +03:00
#
2016-02-07 01:06:56 +03:00
# Check if ROW_NUMBER() works in basic cases
2016-02-05 14:24:35 +03:00
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)
2016-02-14 21:00:05 +03:00
2 1
2016-02-15 18:46:02 +03:00
2 2
2016-02-05 14:24:35 +03:00
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;
2016-02-06 01:53:17 +03:00
#
# 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;
2016-02-16 00:22:12 +02:00
#
# 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
2016-02-16 00:33:53 +02:00
drop table t3;
2016-02-18 01:25:26 +03:00
#
# 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;
2016-02-19 23:20:09 -08:00
#
# 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;
2016-02-26 02:08:45 +03:00
#
# 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;
2016-03-06 23:10:20 +03:00
#
# 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
2016-03-06 23:55:34 +03:00
#
# 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
2016-03-06 23:10:20 +03:00
drop table t4;
2016-03-10 17:46:47 +03:00
#
# 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;