提交 cd84f8f1 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Add optional ORDER BY to MODE aggregate

上级 429cab09
......@@ -3417,15 +3417,23 @@ MEDIAN(X)
"
"Functions (Aggregate)","MODE","
MODE( value ) [ FILTER ( WHERE expression ) ]
MODE( value )
[ ORDER BY { expression [ ASC | DESC ] } ]
[ FILTER ( WHERE expression ) ]
","
Returns the value that occurs with the greatest frequency.
If there are multiple values with the same frequency only one value will be returned.
In this situation value will be chosen based on optional ORDER BY clause
that should specify exactly the same expression as argument of this function.
Use ascending order to get smallest value or descending order to get largest value
from multiple values with the same frequency.
If this clause is not specified the exact chosen value is not determined in this situation.
NULL values are ignored in the calculation.
If no rows are selected, the result is NULL.
Aggregates are only allowed in select statements.
","
MODE(X)
MODE(X ORDER BY X)
"
"Functions (Numeric)","ABS","
......
......@@ -2965,9 +2965,30 @@ public class Parser {
}
break;
}
case MODE:
r = new Aggregate(aggregateType, readExpression(), currentSelect, false);
case MODE: {
Expression expr = readExpression();
r = new Aggregate(aggregateType, expr, currentSelect, false);
if (readIf(ORDER)) {
read("BY");
Expression expr2 = readExpression();
String sql = expr.getSQL();
if (!sql.equals(expr2.getSQL())) {
parseIndex = lastParseIndex;
if (expectedList != null) {
expectedList.clear();
expectedList.add(sql);
}
throw getSyntaxError();
}
ArrayList<SelectOrderBy> orderList = new ArrayList<>(1);
SelectOrderBy order = new SelectOrderBy();
order.expression = expr;
order.sortType = parseSortType();
orderList.add(order);
r.setOrderByList(orderList);
}
break;
}
default:
boolean distinct = readIf(DISTINCT);
r = new Aggregate(aggregateType, readExpression(), currentSelect, distinct);
......
......@@ -382,7 +382,8 @@ public class Aggregate extends Expression {
data = AggregateData.create(type);
select.setCurrentGroupExprData(this, data);
}
if (type == AggregateType.GROUP_CONCAT) {
switch (type) {
case GROUP_CONCAT: {
Value[] array = ((AggregateDataCollecting) data).getArray();
if (array == null) {
return ValueNull.INSTANCE;
......@@ -409,7 +410,8 @@ public class Aggregate extends Expression {
buff.append(s);
}
return ValueString.get(buff.toString());
} else if (type == AggregateType.ARRAY_AGG) {
}
case ARRAY_AGG: {
Value[] array = ((AggregateDataCollecting) data).getArray();
if (array == null) {
return ValueNull.INSTANCE;
......@@ -424,7 +426,15 @@ public class Aggregate extends Expression {
}
return ValueArray.get(array);
}
return data.getValue(session.getDatabase(), dataType, distinct);
case MODE:
if (orderByList != null) {
return ((AggregateDataMode) data).getOrderedValue(session.getDatabase(), dataType,
(orderByList.get(0).sortType & SortOrder.DESCENDING) != 0);
}
//$FALL-THROUGH$
default:
return data.getValue(session.getDatabase(), dataType, distinct);
}
}
@Override
......
......@@ -51,4 +51,30 @@ class AggregateDataMode extends AggregateData {
return v.convertTo(dataType);
}
Value getOrderedValue(Database database, int dataType, boolean desc) {
Value v = ValueNull.INSTANCE;
if (distinctValues != null) {
long count = 0L;
for (Entry<Value, LongDataCounter> entry : distinctValues.entries()) {
long c = entry.getValue().count;
if (c > count) {
v = entry.getKey();
count = c;
} else if (c == count) {
Value v2 = entry.getKey();
int cmp = database.compareTypeSafe(v, v2);
if (desc) {
if (cmp >= 0) {
continue;
}
} else if (cmp <= 0) {
continue;
}
v = v2;
}
}
}
return v.convertTo(dataType);
}
}
......@@ -27,5 +27,20 @@ SELECT MODE(V), MODE(V) FILTER (WHERE (V > 1)), MODE(V) FILTER (WHERE (V < 0)) F
> 1 2 null
> rows: 1
INSERT INTO TEST VALUES (2), (3), (3);
> update count: 3
SELECT MODE(V ORDER BY V) FROM TEST;
>> 1
SELECT MODE(V ORDER BY V ASC) FROM TEST;
>> 1
SELECT MODE(V ORDER BY V DESC) FROM TEST;
>> 3
SELECT MODE(V ORDER BY V + 1) FROM TEST;
> exception SYNTAX_ERROR_2
DROP TABLE TEST;
> ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论