mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Preliminary implementation for the aggregate sum function as a window function
This implementation does not deal with the case where removal of elements from the window frame causes the item to turn to a null value.
This commit is contained in:
42
mysql-test/r/win_sum.result
Normal file
42
mysql-test/r/win_sum.result
Normal file
@ -0,0 +1,42 @@
|
||||
create table t1 (
|
||||
pk int primary key,
|
||||
a int,
|
||||
b int,
|
||||
c real
|
||||
);
|
||||
insert into t1 values
|
||||
(101 , 0, 10, 1.1),
|
||||
(102 , 0, 10, 2.1),
|
||||
(103 , 1, 10, 3.1),
|
||||
(104 , 1, 10, 4.1),
|
||||
(108 , 2, 10, 5.1),
|
||||
(105 , 2, 20, 6.1),
|
||||
(106 , 2, 20, 7.1),
|
||||
(107 , 2, 20, 8.15),
|
||||
(109 , 4, 20, 9.15),
|
||||
(110 , 4, 20, 10.15),
|
||||
(111 , 5, NULL, 11.15),
|
||||
(112 , 5, 1, 12.25),
|
||||
(113 , 5, NULL, 13.35),
|
||||
(114 , 5, NULL, 14.50),
|
||||
(115 , 5, NULL, 15.65);
|
||||
select pk, a, b, sum(b) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING),
|
||||
sum(c) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
|
||||
from t1;
|
||||
pk a b sum(b) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) sum(c) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
|
||||
101 0 10 20 3.2
|
||||
102 0 10 20 3.2
|
||||
103 1 10 20 7.199999999999999
|
||||
104 1 10 20 7.199999999999999
|
||||
105 2 20 40 13.2
|
||||
106 2 20 60 21.35
|
||||
107 2 20 50 20.35
|
||||
108 2 10 30 13.250000000000002
|
||||
109 4 20 40 19.3
|
||||
110 4 20 40 19.3
|
||||
111 5 NULL 1 23.4
|
||||
112 5 1 1 36.75
|
||||
113 5 NULL 1 40.1
|
||||
114 5 NULL 0 43.5
|
||||
115 5 NULL 0 30.15
|
||||
drop table t1;
|
32
mysql-test/t/win_sum.test
Normal file
32
mysql-test/t/win_sum.test
Normal file
@ -0,0 +1,32 @@
|
||||
create table t1 (
|
||||
pk int primary key,
|
||||
a int,
|
||||
b int,
|
||||
c real
|
||||
);
|
||||
|
||||
|
||||
insert into t1 values
|
||||
(101 , 0, 10, 1.1),
|
||||
(102 , 0, 10, 2.1),
|
||||
(103 , 1, 10, 3.1),
|
||||
(104 , 1, 10, 4.1),
|
||||
(108 , 2, 10, 5.1),
|
||||
(105 , 2, 20, 6.1),
|
||||
(106 , 2, 20, 7.1),
|
||||
(107 , 2, 20, 8.15),
|
||||
(109 , 4, 20, 9.15),
|
||||
(110 , 4, 20, 10.15),
|
||||
(111 , 5, NULL, 11.15),
|
||||
(112 , 5, 1, 12.25),
|
||||
(113 , 5, NULL, 13.35),
|
||||
(114 , 5, NULL, 14.50),
|
||||
(115 , 5, NULL, 15.65);
|
||||
|
||||
--sorted_result
|
||||
select pk, a, b, sum(b) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING),
|
||||
sum(c) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
|
||||
|
||||
from t1;
|
||||
|
||||
drop table t1;
|
@ -1318,25 +1318,39 @@ void Item_sum_sum::fix_length_and_dec()
|
||||
bool Item_sum_sum::add()
|
||||
{
|
||||
DBUG_ENTER("Item_sum_sum::add");
|
||||
add_helper(false);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
void Item_sum_sum::add_helper(bool perform_removal)
|
||||
{
|
||||
DBUG_ENTER("Item_sum_sum::add_helper");
|
||||
if (Item_sum_sum::result_type() == DECIMAL_RESULT)
|
||||
{
|
||||
my_decimal value;
|
||||
const my_decimal *val= aggr->arg_val_decimal(&value);
|
||||
if (!aggr->arg_is_null(true))
|
||||
{
|
||||
my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs + (curr_dec_buff^1),
|
||||
val, dec_buffs + curr_dec_buff);
|
||||
if (perform_removal)
|
||||
my_decimal_sub(E_DEC_FATAL_ERROR, dec_buffs + (curr_dec_buff ^ 1),
|
||||
dec_buffs + curr_dec_buff, val);
|
||||
else
|
||||
my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs + (curr_dec_buff ^ 1),
|
||||
val, dec_buffs + curr_dec_buff);
|
||||
curr_dec_buff^= 1;
|
||||
null_value= 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sum+= aggr->arg_val_real();
|
||||
if (perform_removal)
|
||||
sum-= aggr->arg_val_real();
|
||||
else
|
||||
sum+= aggr->arg_val_real();
|
||||
if (!aggr->arg_is_null(true))
|
||||
null_value= 0;
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
@ -1386,6 +1400,13 @@ my_decimal *Item_sum_sum::val_decimal(my_decimal *val)
|
||||
return val_decimal_from_real(val);
|
||||
}
|
||||
|
||||
void Item_sum_sum::remove()
|
||||
{
|
||||
DBUG_ENTER("Item_sum_sum::remove");
|
||||
add_helper(true);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/**
|
||||
Aggregate a distinct row from the distinct hash table.
|
||||
|
||||
|
@ -773,6 +773,10 @@ public:
|
||||
return has_with_distinct() ? "sum(distinct " : "sum(";
|
||||
}
|
||||
Item *copy_or_same(THD* thd);
|
||||
void remove();
|
||||
|
||||
private:
|
||||
void add_helper(bool perform_removal);
|
||||
};
|
||||
|
||||
|
||||
|
@ -1584,6 +1584,7 @@ bool JOIN::process_window_functions(List<Item> *curr_fields_list)
|
||||
}
|
||||
case Item_sum::COUNT_FUNC:
|
||||
case Item_sum::SUM_BIT_FUNC:
|
||||
case Item_sum::SUM_FUNC:
|
||||
{
|
||||
/*
|
||||
Frame-aware window function computation. It does one pass, but
|
||||
|
Reference in New Issue
Block a user