diff --git a/mysql-test/r/win_percent_cume.result b/mysql-test/r/win_percent_cume.result new file mode 100644 index 00000000000..d38c95c9ea7 --- /dev/null +++ b/mysql-test/r/win_percent_cume.result @@ -0,0 +1,62 @@ +create table t1 ( +pk int primary key, +a int, +b int +); +insert into t1 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, +percent_rank() over (order by a), +cume_dist() over (order by a) +from t1; +pk a b percent_rank() over (order by a) cume_dist() over (order by a) +1 0 10 0.0000000000 0.2000000000 +2 0 10 0.0000000000 0.2000000000 +3 1 10 0.2222222222 0.4000000000 +4 1 10 0.2222222222 0.4000000000 +8 2 10 0.4444444444 0.8000000000 +5 2 20 0.4444444444 0.8000000000 +6 2 20 0.4444444444 0.8000000000 +7 2 20 0.4444444444 0.8000000000 +9 4 20 0.8888888889 1.0000000000 +10 4 20 0.8888888889 1.0000000000 +select pk, a, b, +percent_rank() over (order by pk), +cume_dist() over (order by pk) +from t1 order by pk; +pk a b percent_rank() over (order by pk) cume_dist() over (order by pk) +1 0 10 0.0000000000 0.1000000000 +2 0 10 0.1111111111 0.2000000000 +3 1 10 0.2222222222 0.3000000000 +4 1 10 0.3333333333 0.4000000000 +5 2 20 0.4444444444 0.5000000000 +6 2 20 0.5555555556 0.6000000000 +7 2 20 0.6666666667 0.7000000000 +8 2 10 0.7777777778 0.8000000000 +9 4 20 0.8888888889 0.9000000000 +10 4 20 1.0000000000 1.0000000000 +select pk, a, b, +percent_rank() over (partition by a order by a), +cume_dist() over (partition by a order by a) +from t1; +pk a b percent_rank() over (partition by a order by a) cume_dist() over (partition by a order by a) +1 0 10 0.0000000000 1.0000000000 +2 0 10 0.0000000000 1.0000000000 +3 1 10 0.0000000000 1.0000000000 +4 1 10 0.0000000000 1.0000000000 +8 2 10 0.0000000000 1.0000000000 +5 2 20 0.0000000000 1.0000000000 +6 2 20 0.0000000000 1.0000000000 +7 2 20 0.0000000000 1.0000000000 +9 4 20 0.0000000000 1.0000000000 +10 4 20 0.0000000000 1.0000000000 +drop table t1; diff --git a/mysql-test/t/win_percent_cume.test b/mysql-test/t/win_percent_cume.test new file mode 100644 index 00000000000..b851185cb32 --- /dev/null +++ b/mysql-test/t/win_percent_cume.test @@ -0,0 +1,36 @@ +create table t1 ( + pk int primary key, + a int, + b int +); + + +insert into t1 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, + percent_rank() over (order by a), + cume_dist() over (order by a) +from t1; + +select pk, a, b, + percent_rank() over (order by pk), + cume_dist() over (order by pk) +from t1 order by pk; + +select pk, a, b, + percent_rank() over (partition by a order by a), + cume_dist() over (partition by a order by a) +from t1; + +drop table t1; + diff --git a/sql/item_windowfunc.h b/sql/item_windowfunc.h index 1dd483ca9b3..59b739767c8 100644 --- a/sql/item_windowfunc.h +++ b/sql/item_windowfunc.h @@ -422,27 +422,62 @@ class Item_sum_percent_rank: public Item_sum_window_with_row_count window ordering of the window partition of R - NR is defined to be the number of rows in the window partition of R. - Just like with Item_sum_percent_rank, compuation of this function requires + Just like with Item_sum_percent_rank, computation of this function requires two passes. */ -class Item_sum_cume_dist: public Item_sum_percent_rank +class Item_sum_cume_dist: public Item_sum_window_with_row_count { public: - Item_sum_cume_dist(THD *thd) - : Item_sum_percent_rank(thd) {} + Item_sum_cume_dist(THD *thd) : Item_sum_window_with_row_count(thd), + current_row_count_(0) {} - double val_real() { return 0; } + double val_real() + { + if (get_row_count() == 0) + { + null_value= true; + return 0; + } + ulonglong partition_row_count= get_row_count(); + null_value= false; + return static_cast(current_row_count_) / partition_row_count; + } + + bool add() + { + current_row_count_++; + return false; + } enum Sumfunctype sum_func () const { return CUME_DIST_FUNC; } + void clear() + { + current_row_count_= 0; + set_row_count(0); + } + const char*func_name() const { return "cume_dist"; } + + void update_field() {} + enum Item_result result_type () const { return REAL_RESULT; } + enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } + + void fix_length_and_dec() + { + decimals = 10; // TODO-cvicentiu find out how many decimals the standard + // requires. + } + + private: + ulonglong current_row_count_; }; diff --git a/sql/sql_window.cc b/sql/sql_window.cc index 1bfac7ad3cf..f605ed8718d 100644 --- a/sql/sql_window.cc +++ b/sql/sql_window.cc @@ -923,8 +923,8 @@ class Frame_unbounded_following_set_count : public Frame_unbounded_following /* Read the first row */ if (cursor.get_next()) return; - num_rows_in_partition++; } + num_rows_in_partition++; /* Remember which partition we are in */ bound_tracker.check_if_next_group(); @@ -1412,8 +1412,6 @@ bool compute_window_func_with_frames(Item_window_func *item_win, } - - /* Make a list that is a concation of two lists of ORDER elements */ static ORDER* concat_order_lists(MEM_ROOT *mem_root, ORDER *list1, ORDER *list2)