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

Fix GROUPS BETWEEN with same direction

上级 e5d78948
...@@ -269,8 +269,8 @@ public final class WindowFrame { ...@@ -269,8 +269,8 @@ public final class WindowFrame {
*/ */
public Iterator<Value[]> iterator(Session session, ArrayList<Value[]> orderedRows, SortOrder sortOrder, public Iterator<Value[]> iterator(Session session, ArrayList<Value[]> orderedRows, SortOrder sortOrder,
int currentRow, boolean reverse) { int currentRow, boolean reverse) {
int startIndex = getIndex(session, orderedRows, sortOrder, currentRow, starting); int startIndex = getIndex(session, orderedRows, sortOrder, currentRow, starting, false);
int endIndex = following != null ? getIndex(session, orderedRows, sortOrder, currentRow, following) int endIndex = following != null ? getIndex(session, orderedRows, sortOrder, currentRow, following, true)
: currentRow; : currentRow;
if (endIndex < startIndex) { if (endIndex < startIndex) {
throw DbException.get(ErrorCode.SYNTAX_ERROR_1, getSQL()); throw DbException.get(ErrorCode.SYNTAX_ERROR_1, getSQL());
...@@ -293,13 +293,13 @@ public final class WindowFrame { ...@@ -293,13 +293,13 @@ public final class WindowFrame {
} }
private int getIndex(Session session, ArrayList<Value[]> orderedRows, SortOrder sortOrder, int currentRow, private int getIndex(Session session, ArrayList<Value[]> orderedRows, SortOrder sortOrder, int currentRow,
WindowFrameBound bound) { WindowFrameBound bound, boolean forFollowing) {
int size = orderedRows.size(); int size = orderedRows.size();
int last = size - 1; int last = size - 1;
int index; int index;
switch (bound.getType()) { switch (bound.getType()) {
case UNBOUNDED_PRECEDING: case UNBOUNDED_PRECEDING:
index = 0; index = -1;
break; break;
case PRECEDING: case PRECEDING:
switch (units) { switch (units) {
...@@ -310,13 +310,25 @@ public final class WindowFrame { ...@@ -310,13 +310,25 @@ public final class WindowFrame {
} }
case GROUPS: { case GROUPS: {
int value = getIntOffset(bound, session); int value = getIntOffset(bound, session);
index = toGroupStart(orderedRows, sortOrder, currentRow, 0); if (!forFollowing) {
while (value > 0 && index > 0) { index = toGroupStart(orderedRows, sortOrder, currentRow, 0);
value--; while (value > 0 && index > 0) {
index = toGroupStart(orderedRows, sortOrder, index - 1, 0); value--;
} index = toGroupStart(orderedRows, sortOrder, index - 1, 0);
if (value > 0) { }
index = -1; if (value > 0) {
index = -1;
}
} else {
if (value == 0) {
index = toGroupEnd(orderedRows, sortOrder, currentRow, last);
} else {
index = currentRow;
while (value > 0 && index >= 0) {
value--;
index = toGroupStart(orderedRows, sortOrder, index, 0) - 1;
}
}
} }
break; break;
} }
...@@ -353,13 +365,25 @@ public final class WindowFrame { ...@@ -353,13 +365,25 @@ public final class WindowFrame {
} }
case GROUPS: { case GROUPS: {
int value = getIntOffset(bound, session); int value = getIntOffset(bound, session);
index = toGroupEnd(orderedRows, sortOrder, currentRow, last); if (forFollowing) {
while (value > 0 && index < last) { index = toGroupEnd(orderedRows, sortOrder, currentRow, last);
value--; while (value > 0 && index < last) {
index = toGroupEnd(orderedRows, sortOrder, index + 1, last); value--;
} index = toGroupEnd(orderedRows, sortOrder, index + 1, last);
if (value > 0) { }
index = size; if (value > 0) {
index = size;
}
} else {
if (value == 0) {
index = toGroupStart(orderedRows, sortOrder, currentRow, 0);
} else {
index = currentRow;
while (value > 0 && index <= last) {
value--;
index = toGroupEnd(orderedRows, sortOrder, index, last) + 1;
}
}
} }
break; break;
} }
...@@ -386,7 +410,7 @@ public final class WindowFrame { ...@@ -386,7 +410,7 @@ public final class WindowFrame {
} }
break; break;
case UNBOUNDED_FOLLOWING: case UNBOUNDED_FOLLOWING:
index = last; index = size;
break; break;
default: default:
throw DbException.getUnsupportedException("window frame bound type=" + bound.getType()); throw DbException.getUnsupportedException("window frame bound type=" + bound.getType());
......
...@@ -323,6 +323,49 @@ SELECT *, ARRAY_AGG(ID) OVER (ORDER BY ID ROWS BETWEEN 2 PRECEDING AND 1 PRECEDI ...@@ -323,6 +323,49 @@ SELECT *, ARRAY_AGG(ID) OVER (ORDER BY ID ROWS BETWEEN 2 PRECEDING AND 1 PRECEDI
> 4 8 (2, 3) > 4 8 (2, 3)
> rows (ordered): 4 > rows (ordered): 4
SELECT *, ARRAY_AGG(ID) OVER (ORDER BY ID ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING) FROM TEST OFFSET 4 ROWS;
> ID VALUE ARRAY_AGG(ID) OVER (ORDER BY ID ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING)
> -- ----- -------------------------------------------------------------------------
> 5 8 (6, 7)
> 6 8 (7, 8)
> 7 9 (8)
> 8 9 null
> rows (ordered): 4
SELECT *,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) U_P,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN 2 PRECEDING AND 1 PRECEDING) P,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN 1 FOLLOWING AND 2 FOLLOWING) F,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING) U_F
FROM TEST;
> ID VALUE U_P P F U_F
> -- ----- ------------------ ------------ --------------- ------------------
> 1 1 null null (3, 4, 5, 6) (3, 4, 5, 6, 7, 8)
> 2 1 null null (3, 4, 5, 6) (3, 4, 5, 6, 7, 8)
> 3 5 (1, 2) (1, 2) (4, 5, 6, 7, 8) (4, 5, 6, 7, 8)
> 4 8 (1, 2, 3) (1, 2, 3) (7, 8) (7, 8)
> 5 8 (1, 2, 3) (1, 2, 3) (7, 8) (7, 8)
> 6 8 (1, 2, 3) (1, 2, 3) (7, 8) (7, 8)
> 7 9 (1, 2, 3, 4, 5, 6) (3, 4, 5, 6) null null
> 8 9 (1, 2, 3, 4, 5, 6) (3, 4, 5, 6) null null
> rows (ordered): 8
SELECT *,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN 1 PRECEDING AND 0 PRECEDING) P,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN 0 FOLLOWING AND 1 FOLLOWING) F
FROM TEST;
> ID VALUE P F
> -- ----- --------------- ---------------
> 1 1 (1, 2) (1, 2, 3)
> 2 1 (1, 2) (1, 2, 3)
> 3 5 (1, 2, 3) (3, 4, 5, 6)
> 4 8 (3, 4, 5, 6) (4, 5, 6, 7, 8)
> 5 8 (3, 4, 5, 6) (4, 5, 6, 7, 8)
> 6 8 (3, 4, 5, 6) (4, 5, 6, 7, 8)
> 7 9 (4, 5, 6, 7, 8) (7, 8)
> 8 9 (4, 5, 6, 7, 8) (7, 8)
> rows (ordered): 8
SELECT *, ARRAY_AGG(ID) OVER (ORDER BY ID RANGE BETWEEN CURRENT ROW AND 1 PRECEDING) FROM TEST; SELECT *, ARRAY_AGG(ID) OVER (ORDER BY ID RANGE BETWEEN CURRENT ROW AND 1 PRECEDING) FROM TEST;
> exception SYNTAX_ERROR_1 > exception SYNTAX_ERROR_1
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论