diff --git a/docs/generated/sql/aggregates.md b/docs/generated/sql/aggregates.md
index 41ccfc184264..84b0671b82cb 100644
--- a/docs/generated/sql/aggregates.md
+++ b/docs/generated/sql/aggregates.md
@@ -37,6 +37,8 @@
bool_or(arg1: bool) → bool | Calculates the boolean value of OR ing all selected values.
diff --git a/pkg/sql/logictest/testdata/logic_test/aggregate b/pkg/sql/logictest/testdata/logic_test/aggregate
index 05e46a06d60b..1c78f8994bf3 100644
--- a/pkg/sql/logictest/testdata/logic_test/aggregate
+++ b/pkg/sql/logictest/testdata/logic_test/aggregate
@@ -5,7 +5,8 @@ CREATE TABLE kv (
k INT PRIMARY KEY,
v INT,
w INT,
- s STRING
+ s STRING,
+ i INTERVAL
)
# Aggregate functions return NULL if there are no rows.
@@ -36,6 +37,11 @@ SELECT jsonb_agg(1) FROM kv
----
NULL
+query TTTT
+SELECT min(i), avg(i), max(i), sum(i) FROM kv
+----
+NULL NULL NULL NULL
+
query IIIIRRRRBBT
SELECT min(v), max(v), count(v), sum_int(1), avg(v), sum(v), stddev(v), variance(v), bool_and(v = 1), bool_and(v = 1), xor_agg(s::bytes) FROM kv
----
@@ -147,12 +153,12 @@ SELECT (SELECT COALESCE(max(1), 0) FROM generate_series(1,0))
statement OK
INSERT INTO kv VALUES
-(1, 2, 3, 'a'),
-(3, 4, 5, 'a'),
-(5, NULL, 5, NULL),
-(6, 2, 3, 'b'),
-(7, 2, 2, 'b'),
-(8, 4, 2, 'A')
+(1, 2, 3, 'a', '1min'),
+(3, 4, 5, 'a', '2sec'),
+(5, NULL, 5, NULL, NULL),
+(6, 2, 3, 'b', '1ms'),
+(7, 2, 2, 'b', '4 days'),
+(8, 4, 2, 'A', '3 years')
# Aggregate functions triggers aggregation and computation for every row even when applied to a constant.
# NB: The XOR result is 00 because \x01 is XOR'd an even number of times.
@@ -588,6 +594,11 @@ SELECT avg(k), avg(v), sum(k), sum(v) FROM kv
----
5 2.8 30 14
+query TTTT
+SELECT min(i), avg(i), max(i), sum(i) FROM kv
+----
+00:00:00.001 7 mons 6 days 19:12:12.4002 3 years 3 years 4 days 00:01:02.001
+
query RRRR
SELECT avg(k::decimal), avg(v::decimal), sum(k::decimal), sum(v::decimal) FROM kv
----
diff --git a/pkg/sql/logictest/testdata/logic_test/window b/pkg/sql/logictest/testdata/logic_test/window
index c2e644a6a4e5..e349a116ba2d 100644
--- a/pkg/sql/logictest/testdata/logic_test/window
+++ b/pkg/sql/logictest/testdata/logic_test/window
@@ -10,6 +10,7 @@ CREATE TABLE kv (
d DECIMAL,
s STRING,
b BOOL,
+ i INTERVAL,
FAMILY (k, v, w, f, b),
FAMILY (d),
FAMILY (s)
@@ -17,12 +18,12 @@ CREATE TABLE kv (
statement OK
INSERT INTO kv VALUES
-(1, 2, 3, 1.0, 1, 'a', true),
-(3, 4, 5, 2, 8, 'a', true),
-(5, NULL, 5, 9.9, -321, NULL, false),
-(6, 2, 3, 4.4, 4.4, 'b', true),
-(7, 2, 2, 6, 7.9, 'b', true),
-(8, 4, 2, 3, 3, 'A', false)
+(1, 2, 3, 1.0, 1, 'a', true, '1min'),
+(3, 4, 5, 2, 8, 'a', true, '2sec'),
+(5, NULL, 5, 9.9, -321, NULL, false, NULL),
+(6, 2, 3, 4.4, 4.4, 'b', true, '1ms'),
+(7, 2, 2, 6, 7.9, 'b', true, '4 days'),
+(8, 4, 2, 3, 3, 'A', false, '3 years')
query error window functions are not allowed in GROUP BY
SELECT * FROM kv GROUP BY v, count(w) OVER ()
@@ -210,38 +211,38 @@ SELECT avg(k) OVER (w ORDER BY w) FROM kv WINDOW w AS (PARTITION BY v) ORDER BY
7
8
-query IIIRRTBR colnames
+query IIIRRTBTR colnames
SELECT *, avg(k) OVER (w ORDER BY w) FROM kv WINDOW w AS (PARTITION BY v) ORDER BY 1
----
-k v w f d s b avg
-1 2 3 1 1 a true 4.6666666666666666667
-3 4 5 2 8 a true 5.5
-5 NULL 5 9.9 -321 NULL false 5
-6 2 3 4.4 4.4 b true 4.6666666666666666667
-7 2 2 6 7.9 b true 7
-8 4 2 3 3 A false 8
+k v w f d s b i avg
+1 2 3 1 1 a true 00:01:00 4.6666666666666666667
+3 4 5 2 8 a true 00:00:02 5.5
+5 NULL 5 9.9 -321 NULL false NULL 5
+6 2 3 4.4 4.4 b true 00:00:00.001 4.6666666666666666667
+7 2 2 6 7.9 b true 4 days 7
+8 4 2 3 3 A false 3 years 8
-query IIIRRTBR colnames
+query IIIRRTBTR colnames
SELECT *, avg(k) OVER w FROM kv WINDOW w AS (PARTITION BY v ORDER BY w) ORDER BY avg(k) OVER w, k
----
-k v w f d s b avg
-1 2 3 1 1 a true 4.6666666666666666667
-6 2 3 4.4 4.4 b true 4.6666666666666666667
-5 NULL 5 9.9 -321 NULL false 5
-3 4 5 2 8 a true 5.5
-7 2 2 6 7.9 b true 7
-8 4 2 3 3 A false 8
+k v w f d s b i avg
+1 2 3 1 1 a true 00:01:00 4.6666666666666666667
+6 2 3 4.4 4.4 b true 00:00:00.001 4.6666666666666666667
+5 NULL 5 9.9 -321 NULL false NULL 5
+3 4 5 2 8 a true 00:00:02 5.5
+7 2 2 6 7.9 b true 4 days 7
+8 4 2 3 3 A false 3 years 8
-query IIIRRTB colnames
+query IIIRRTBT colnames
SELECT * FROM kv WINDOW w AS (PARTITION BY v ORDER BY w) ORDER BY avg(k) OVER w DESC, k
----
-k v w f d s b
-8 4 2 3 3 A false
-7 2 2 6 7.9 b true
-3 4 5 2 8 a true
-5 NULL 5 9.9 -321 NULL false
-1 2 3 1 1 a true
-6 2 3 4.4 4.4 b true
+k v w f d s b i
+8 4 2 3 3 A false 3 years
+7 2 2 6 7.9 b true 4 days
+3 4 5 2 8 a true 00:00:02
+5 NULL 5 9.9 -321 NULL false NULL
+1 2 3 1 1 a true 00:01:00
+6 2 3 4.4 4.4 b true 00:00:00.001
query error window "w" is already defined
SELECT avg(k) OVER w FROM kv WINDOW w AS (), w AS ()
@@ -1900,6 +1901,20 @@ DELETE FROM kv WHERE k = 12
query error FILTER specified but rank\(\) is not an aggregate function
SELECT k, rank() FILTER (WHERE k=1) OVER () FROM kv
+query TT
+SELECT i, avg(i) OVER (ORDER BY i) FROM kv ORDER BY i
+----
+NULL NULL
+NULL NULL
+NULL NULL
+NULL NULL
+00:00:00.001 00:00:00.001
+00:00:02 00:00:01.0005
+00:01:00 00:00:20.667
+4 days 1 day 00:00:15.50025
+3 years 7 mons 6 days 19:12:12.4002
+
+
# Issue #14606: correctly handle aggregation functions above the windowing level
query I
SELECT max(i) * (row_number() OVER (ORDER BY max(i))) FROM (SELECT 1 AS i, 2 AS j) GROUP BY j
diff --git a/pkg/sql/sem/builtins/aggregate_builtins.go b/pkg/sql/sem/builtins/aggregate_builtins.go
index 3532d2727bcb..ddf68372efa0 100644
--- a/pkg/sql/sem/builtins/aggregate_builtins.go
+++ b/pkg/sql/sem/builtins/aggregate_builtins.go
@@ -125,6 +125,8 @@ var aggregates = map[string]builtinDefinition{
"Calculates the average of the selected values."),
makeAggOverload([]*types.T{types.Decimal}, types.Decimal, newDecimalAvgAggregate,
"Calculates the average of the selected values."),
+ makeAggOverload([]*types.T{types.Interval}, types.Interval, newIntervalAvgAggregate,
+ "Calculates the average of the selected values."),
),
"bool_and": makeBuiltin(aggProps(),
@@ -557,6 +559,11 @@ func newDecimalAvgAggregate(
) tree.AggregateFunc {
return &avgAggregate{agg: newDecimalSumAggregate(params, evalCtx, arguments)}
}
+func newIntervalAvgAggregate(
+ params []*types.T, evalCtx *tree.EvalContext, arguments tree.Datums,
+) tree.AggregateFunc {
+ return &avgAggregate{agg: newIntervalSumAggregate(params, evalCtx, arguments)}
+}
// Add accumulates the passed datum into the average.
func (a *avgAggregate) Add(ctx context.Context, datum tree.Datum, other ...tree.Datum) error {
@@ -586,6 +593,8 @@ func (a *avgAggregate) Result() (tree.Datum, error) {
count := apd.New(int64(a.count), 0)
_, err := tree.DecimalCtx.Quo(&t.Decimal, &t.Decimal, count)
return t, err
+ case *tree.DInterval:
+ return &tree.DInterval{Duration: t.Duration.Div(int64(a.count))}, nil
default:
return nil, errors.AssertionFailedf("unexpected SUM result type: %s", t)
}
diff --git a/pkg/sql/sem/builtins/aggregate_builtins_test.go b/pkg/sql/sem/builtins/aggregate_builtins_test.go
index 3b54bb162ef5..2de43dbc7071 100644
--- a/pkg/sql/sem/builtins/aggregate_builtins_test.go
+++ b/pkg/sql/sem/builtins/aggregate_builtins_test.go
@@ -74,6 +74,10 @@ func TestAvgDecimalResultDeepCopy(t *testing.T) {
testAggregateResultDeepCopy(t, newDecimalAvgAggregate, makeDecimalTestDatum(10))
}
+func TestAvgIntervalResultDeepCopy(t *testing.T) {
+ testAggregateResultDeepCopy(t, newIntervalAvgAggregate, makeIntervalTestDatum(10))
+}
+
func TestBoolAndResultDeepCopy(t *testing.T) {
testAggregateResultDeepCopy(t, newBoolAndAggregate, makeBoolTestDatum(10))
}
@@ -329,6 +333,14 @@ func BenchmarkAvgAggregateDecimal(b *testing.B) {
}
}
+func BenchmarkAvgAggregateInterval(b *testing.B) {
+ for _, count := range []int{1000} {
+ b.Run(fmt.Sprintf("count=%d", count), func(b *testing.B) {
+ runBenchmarkAggregate(b, newIntervalAvgAggregate, makeIntervalTestDatum(count))
+ })
+ }
+}
+
func BenchmarkCountAggregate(b *testing.B) {
for _, count := range []int{1000} {
b.Run(fmt.Sprintf("count=%d", count), func(b *testing.B) {
diff --git a/pkg/sql/sem/builtins/window_frame_builtins.go b/pkg/sql/sem/builtins/window_frame_builtins.go
index 3b8a7097a35c..609ae8383ae0 100644
--- a/pkg/sql/sem/builtins/window_frame_builtins.go
+++ b/pkg/sql/sem/builtins/window_frame_builtins.go
@@ -408,6 +408,8 @@ func (w *avgWindowFunc) Compute(
count := apd.New(int64(frameSize), 0)
_, err := tree.DecimalCtx.Quo(&avg.Decimal, &dd.Decimal, count)
return &avg, err
+ case *tree.DInterval:
+ return &tree.DInterval{Duration: t.Duration.Div(int64(frameSize))}, nil
default:
return nil, errors.AssertionFailedf("unexpected SUM result type: %s", t)
}
|