Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
4f73254a
提交
4f73254a
authored
7 年前
作者:
Evgenij Ryazanov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add optimized implementation of MEDIAN aggregate for cases with indexed columns with nulls first
上级
ed2b0249
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
311 行增加
和
2 行删除
+311
-2
Aggregate.java
h2/src/main/org/h2/expression/Aggregate.java
+73
-1
AggregateDataMedian.java
h2/src/main/org/h2/expression/AggregateDataMedian.java
+4
-1
median.sql
...c/test/org/h2/test/scripts/functions/aggregate/median.sql
+234
-0
没有找到文件。
h2/src/main/org/h2/expression/Aggregate.java
浏览文件 @
4f73254a
...
@@ -20,6 +20,7 @@ import org.h2.result.SearchRow;
...
@@ -20,6 +20,7 @@ import org.h2.result.SearchRow;
import
org.h2.result.SortOrder
;
import
org.h2.result.SortOrder
;
import
org.h2.table.Column
;
import
org.h2.table.Column
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.IndexColumn
;
import
org.h2.table.Table
;
import
org.h2.table.Table
;
import
org.h2.table.TableFilter
;
import
org.h2.table.TableFilter
;
import
org.h2.util.StatementBuilder
;
import
org.h2.util.StatementBuilder
;
...
@@ -293,7 +294,7 @@ public class Aggregate extends Expression {
...
@@ -293,7 +294,7 @@ public class Aggregate extends Expression {
Table
table
=
select
.
getTopTableFilter
().
getTable
();
Table
table
=
select
.
getTopTableFilter
().
getTable
();
return
ValueLong
.
get
(
table
.
getRowCount
(
session
));
return
ValueLong
.
get
(
table
.
getRowCount
(
session
));
case
MIN:
case
MIN:
case
MAX:
case
MAX:
{
boolean
first
=
type
==
AggregateType
.
MIN
;
boolean
first
=
type
==
AggregateType
.
MIN
;
Index
index
=
getMinMaxColumnIndex
();
Index
index
=
getMinMaxColumnIndex
();
int
sortType
=
index
.
getIndexColumns
()[
0
].
sortType
;
int
sortType
=
index
.
getIndexColumns
()[
0
].
sortType
;
...
@@ -309,6 +310,54 @@ public class Aggregate extends Expression {
...
@@ -309,6 +310,54 @@ public class Aggregate extends Expression {
v
=
row
.
getValue
(
index
.
getColumns
()[
0
].
getColumnId
());
v
=
row
.
getValue
(
index
.
getColumns
()[
0
].
getColumnId
());
}
}
return
v
;
return
v
;
}
case
MEDIAN:
{
Index
index
=
getMinMaxColumnIndex
();
long
count
=
index
.
getRowCount
(
session
);
if
(
count
==
0
)
{
return
ValueNull
.
INSTANCE
;
}
Cursor
cursor
=
index
.
find
(
session
,
null
,
null
);
cursor
.
next
();
// Skip nulls
SearchRow
row
;
while
(
count
>
0
)
{
row
=
cursor
.
getSearchRow
();
if
(
row
==
null
)
{
return
ValueNull
.
INSTANCE
;
}
if
(
row
.
getValue
(
index
.
getColumns
()[
0
].
getColumnId
())
==
ValueNull
.
INSTANCE
)
{
count
--;
cursor
.
next
();
}
else
break
;
}
if
(
count
==
0
)
{
return
ValueNull
.
INSTANCE
;
}
long
skip
=
(
count
-
1
)
/
2
;
for
(
int
i
=
0
;
i
<
skip
;
i
++)
{
cursor
.
next
();
row
=
cursor
.
getSearchRow
();
}
row
=
cursor
.
getSearchRow
();
Value
v
;
if
(
row
==
null
)
{
v
=
ValueNull
.
INSTANCE
;
}
else
{
v
=
row
.
getValue
(
index
.
getColumns
()[
0
].
getColumnId
());
}
if
((
count
&
1
)
==
0
)
{
cursor
.
next
();
row
=
cursor
.
getSearchRow
();
if
(
row
==
null
)
{
return
v
;
}
Value
v2
=
row
.
getValue
(
index
.
getColumns
()[
0
].
getColumnId
());
return
AggregateDataMedian
.
getMedian
(
v
,
v2
,
dataType
,
session
.
getDatabase
().
getCompareMode
());
}
return
v
;
}
default
:
default
:
DbException
.
throwInternalError
(
"type="
+
type
);
DbException
.
throwInternalError
(
"type="
+
type
);
}
}
...
@@ -616,6 +665,29 @@ public class Aggregate extends Expression {
...
@@ -616,6 +665,29 @@ public class Aggregate extends Expression {
case
MAX:
case
MAX:
Index
index
=
getMinMaxColumnIndex
();
Index
index
=
getMinMaxColumnIndex
();
return
index
!=
null
;
return
index
!=
null
;
case
MEDIAN:
if
(
distinct
)
{
return
false
;
}
index
=
getMinMaxColumnIndex
();
if
(
index
==
null
)
{
return
false
;
}
IndexColumn
ic
=
index
.
getIndexColumns
()[
0
];
if
(!
ic
.
column
.
isNullable
())
{
return
true
;
}
int
sortType
=
ic
.
sortType
;
// Nulls last is not supported
if
((
sortType
&
SortOrder
.
NULLS_LAST
)
!=
0
)
return
false
;
// Ascending is supported
if
((
sortType
&
SortOrder
.
DESCENDING
)
==
0
)
return
true
;
// Descending with nulls first is also supported
if
((
sortType
&
SortOrder
.
NULLS_FIRST
)
!=
0
)
return
true
;
return
false
;
default
:
default
:
return
false
;
return
false
;
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/expression/AggregateDataMedian.java
浏览文件 @
4f73254a
...
@@ -68,7 +68,10 @@ class AggregateDataMedian extends AggregateData {
...
@@ -68,7 +68,10 @@ class AggregateDataMedian extends AggregateData {
if
((
len
&
1
)
==
1
)
{
if
((
len
&
1
)
==
1
)
{
return
v1
.
convertTo
(
dataType
);
return
v1
.
convertTo
(
dataType
);
}
}
Value
v0
=
a
[
idx
-
1
];
return
getMedian
(
a
[
idx
-
1
],
v1
,
dataType
,
mode
);
}
static
Value
getMedian
(
Value
v0
,
Value
v1
,
int
dataType
,
CompareMode
mode
)
{
if
(
v0
.
compareTo
(
v1
,
mode
)
==
0
)
{
if
(
v0
.
compareTo
(
v1
,
mode
)
==
0
)
{
return
v1
.
convertTo
(
dataType
);
return
v1
.
convertTo
(
dataType
);
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/scripts/functions/aggregate/median.sql
浏览文件 @
4f73254a
...
@@ -3,6 +3,240 @@
...
@@ -3,6 +3,240 @@
-- Initial Developer: H2 Group
-- Initial Developer: H2 Group
--
--
-- ASC
create
table
test
(
v
tinyint
);
>
ok
create
index
test_idx
on
test
(
v
asc
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
-- ASC NULLS FIRST
create
table
test
(
v
tinyint
);
>
ok
create
index
test_idx
on
test
(
v
asc
nulls
first
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
-- ASC NULLS LAST
create
table
test
(
v
tinyint
);
>
ok
create
index
test_idx
on
test
(
v
asc
nulls
last
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
-- DESC
create
table
test
(
v
tinyint
);
>
ok
create
index
test_idx
on
test
(
v
desc
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
-- DESC NULLS FIRST
create
table
test
(
v
tinyint
);
>
ok
create
index
test_idx
on
test
(
v
desc
nulls
first
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
-- DESC NULLS LAST
create
table
test
(
v
tinyint
);
>
ok
create
index
test_idx
on
test
(
v
desc
nulls
last
);
>
ok
insert
into
test
values
(
20
),
(
20
),
(
10
);
>
update
count
:
3
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
insert
into
test
values
(
null
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
20
select
median
(
distinct
v
)
from
test
;
>
MEDIAN
(
DISTINCT
V
)
>
------------------
>
15
insert
into
test
values
(
10
);
>
update
count
:
1
select
median
(
v
)
from
test
;
>
MEDIAN
(
V
)
>
---------
>
15
drop
table
test
;
>
ok
create
table
test
(
v
tinyint
);
create
table
test
(
v
tinyint
);
>
ok
>
ok
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论