mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-9787: Window functions: HAVING and GROUP BY
- Hook window function computation into the right location. - Add a testcase which shows that HAVING is now checked before the window function computation step.
This commit is contained in:
@@ -1472,5 +1472,34 @@ EXPLAIN
|
||||
}
|
||||
}
|
||||
}
|
||||
#
|
||||
# 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": {
|
||||
"window_functions_computation": {
|
||||
"temporary_table": {
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ALL",
|
||||
"rows": 10,
|
||||
"filtered": 100
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
drop table t1;
|
||||
drop table t0;
|
||||
|
@@ -950,7 +950,14 @@ from t1
|
||||
group by a
|
||||
order by null;
|
||||
|
||||
--echo #
|
||||
--echo # Check how window function works together with GROUP BY and HAVING
|
||||
--echo #
|
||||
|
||||
select b,max(a) as MX, rank() over (order by b) from t1 group by b having MX in (3,5,7);
|
||||
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);
|
||||
|
||||
drop table t1;
|
||||
drop table t0;
|
||||
|
||||
|
||||
|
@@ -2333,14 +2333,6 @@ bool JOIN::make_aggr_tables_info()
|
||||
curr_tab->fields= &tmp_fields_list1;
|
||||
set_postjoin_aggr_write_func(curr_tab);
|
||||
|
||||
// psergey-todo: this is probably an incorrect place:
|
||||
if (select_lex->window_funcs.elements)
|
||||
{
|
||||
curr_tab->window_funcs_step= new Window_funcs_computation;
|
||||
if (curr_tab->window_funcs_step->setup(thd, &select_lex->window_funcs))
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
tmp_table_param.func_count= 0;
|
||||
tmp_table_param.field_count+= tmp_table_param.func_count;
|
||||
if (sort_and_group || curr_tab->table->group)
|
||||
@@ -2652,6 +2644,24 @@ bool JOIN::make_aggr_tables_info()
|
||||
skip_sort_order= true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Window functions computation step should be attached to the last join_tab
|
||||
that's doing aggregation.
|
||||
The last join_tab reads the data from the temp. table. It also may do
|
||||
- sorting
|
||||
- duplicate value removal
|
||||
Both of these operations are done after window function computation step.
|
||||
*/
|
||||
curr_tab= join_tab + top_join_tab_count + aggr_tables - 1;
|
||||
if (select_lex->window_funcs.elements)
|
||||
{
|
||||
curr_tab->window_funcs_step= new Window_funcs_computation;
|
||||
if (curr_tab->window_funcs_step->setup(thd, &select_lex->window_funcs,
|
||||
curr_tab))
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
fields= curr_fields_list;
|
||||
// Reset before execution
|
||||
set_items_ref_array(items0);
|
||||
|
@@ -1565,11 +1565,20 @@ bool Window_func_runner::exec(JOIN *join)
|
||||
|
||||
|
||||
bool Window_funcs_computation::setup(THD *thd,
|
||||
List<Item_window_func> *window_funcs)
|
||||
List<Item_window_func> *window_funcs,
|
||||
JOIN_TAB *tab)
|
||||
{
|
||||
List_iterator_fast<Item_window_func> it(*window_funcs);
|
||||
Item_window_func *item_win;
|
||||
Window_func_runner *runner;
|
||||
|
||||
SQL_SELECT *sel= NULL;
|
||||
if (tab->filesort && tab->filesort->select)
|
||||
{
|
||||
sel= tab->filesort->select;
|
||||
DBUG_ASSERT(!sel->quick);
|
||||
}
|
||||
|
||||
// for each window function
|
||||
while ((item_win= it++))
|
||||
{
|
||||
@@ -1579,6 +1588,8 @@ bool Window_funcs_computation::setup(THD *thd,
|
||||
{
|
||||
return true;
|
||||
}
|
||||
/* Apply the same condition that the subsequent sort will */
|
||||
runner->filesort->select= sel;
|
||||
win_func_runners.push_back(runner, thd->mem_root);
|
||||
}
|
||||
return false;
|
||||
|
@@ -171,9 +171,11 @@ public:
|
||||
bool exec(JOIN *join);
|
||||
|
||||
void cleanup() { delete filesort; }
|
||||
|
||||
friend class Window_funcs_computation;
|
||||
};
|
||||
|
||||
|
||||
struct st_join_table;
|
||||
/*
|
||||
This is a "window function computation phase": a single object of this class
|
||||
takes care of computing all window functions in a SELECT.
|
||||
@@ -187,7 +189,7 @@ class Window_funcs_computation : public Sql_alloc
|
||||
{
|
||||
List<Window_func_runner> win_func_runners;
|
||||
public:
|
||||
bool setup(THD *thd, List<Item_window_func> *window_funcs);
|
||||
bool setup(THD *thd, List<Item_window_func> *window_funcs, st_join_table *tab);
|
||||
bool exec(JOIN *join);
|
||||
void cleanup();
|
||||
};
|
||||
|
Reference in New Issue
Block a user