diff --git a/src/query-builder/aggregate-function-builder.ts b/src/query-builder/aggregate-function-builder.ts index ebd559fbf..e71c7f8b6 100644 --- a/src/query-builder/aggregate-function-builder.ts +++ b/src/query-builder/aggregate-function-builder.ts @@ -12,7 +12,7 @@ import { } from '../expression/expression.js' import { ReferenceExpression, - StringReference, + SimpleReferenceExpression, } from '../parser/reference-parser.js' import { ComparisonOperatorExpression, @@ -22,7 +22,6 @@ import { } from '../parser/binary-operation-parser.js' import { SqlBool } from '../util/type-utils.js' import { ExpressionOrFactory } from '../parser/expression-parser.js' -import { DynamicReferenceBuilder } from '../dynamic/dynamic-reference-builder.js' import { OrderByDirectionExpression, parseOrderBy, @@ -126,7 +125,7 @@ export class AggregateFunctionBuilder * inner join "pet" ON "pet"."owner_id" = "person"."id" * ``` */ - orderBy | DynamicReferenceBuilder>( + orderBy>( orderBy: OE, direction?: OrderByDirectionExpression, ): AggregateFunctionBuilder { @@ -139,6 +138,45 @@ export class AggregateFunctionBuilder }) } + /** + * Adds a `withing group` clause with a nested `order by` clause after the function. + * + * ### Examples + * + * Most frequent person name: + * + * ```ts + * const result = await db + * .selectFrom('person') + * .select((eb) => [ + * eb.fn + * .agg('mode') + * .withinGroupOrderBy('person.name') + * .as('most_frequent_name') + * ]) + * .executeTakeFirstOrThrow() + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * select mode() within group (order by "person"."name") as "most_frequent_name" + * from "person" + * ``` + */ + withinGroupOrderBy>( + orderBy: OE, + direction?: OrderByDirectionExpression, + ): AggregateFunctionBuilder { + return new AggregateFunctionBuilder({ + ...this.#props, + aggregateFunctionNode: AggregateFunctionNode.cloneWithWithinGroup( + this.#props.aggregateFunctionNode, + parseOrderBy([orderBy, direction]), + ), + }) + } + /** * Adds a `filter` clause with a nested `where` clause after the function. *