Skip to content

Commit 1ea0dc2

Browse files
authored
fix(postgres): Support WITHIN GROUP ( order_by_clause ) FILTER for Postgres (#4652)
* Support filter in aggregates * Support only for Postgres * lint * Default on * Feedback minus _parse_window
1 parent fab2efc commit 1ea0dc2

File tree

4 files changed

+17
-3
lines changed

4 files changed

+17
-3
lines changed

sqlglot/expressions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1577,7 +1577,7 @@ def recursive(self) -> bool:
15771577

15781578

15791579
class WithinGroup(Expression):
1580-
arg_types = {"this": True, "expression": False}
1580+
arg_types = {"this": True, "expression": False, "filter": False}
15811581

15821582

15831583
# clickhouse supports scalar ctes

sqlglot/generator.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2724,7 +2724,11 @@ def windowspec_sql(self, expression: exp.WindowSpec) -> str:
27242724
def withingroup_sql(self, expression: exp.WithinGroup) -> str:
27252725
this = self.sql(expression, "this")
27262726
expression_sql = self.sql(expression, "expression")[1:] # order has a leading space
2727-
return f"{this} WITHIN GROUP ({expression_sql})"
2727+
filter_sql = self.sql(expression, "filter")[1:]
2728+
result = f"{this} WITHIN GROUP ({expression_sql})"
2729+
if filter_sql:
2730+
result = f"{result} FILTER ({filter_sql})"
2731+
return result
27282732

27292733
def between_sql(self, expression: exp.Between) -> str:
27302734
this = self.sql(expression, "this")

sqlglot/parser.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6614,7 +6614,13 @@ def _parse_window(
66146614
# https://learn.microsoft.com/en-us/sql/t-sql/functions/percentile-disc-transact-sql?view=sql-server-ver16
66156615
if self._match_text_seq("WITHIN", "GROUP"):
66166616
order = self._parse_wrapped(self._parse_order)
6617-
this = self.expression(exp.WithinGroup, this=this, expression=order)
6617+
if self._match(TokenType.FILTER):
6618+
where_clause = self._parse_wrapped(self._parse_where)
6619+
this = self.expression(
6620+
exp.WithinGroup, this=this, expression=order, filter=where_clause
6621+
)
6622+
else:
6623+
this = self.expression(exp.WithinGroup, this=this, expression=order)
66186624

66196625
# SQL spec defines an optional [ { IGNORE | RESPECT } NULLS ] OVER
66206626
# Some dialects choose to implement and some do not.

tests/dialects/test_postgres.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,10 @@ def test_postgres(self):
833833
"/* + some comment */ SELECT b.foo, b.bar FROM baz AS b",
834834
)
835835

836+
self.validate_identity(
837+
"SELECT PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY a) FILTER (WHERE CAST(b AS BOOLEAN)) AS mean_value FROM (VALUES (0, 't')) AS fake_data(a, b)"
838+
)
839+
836840
def test_ddl(self):
837841
# Checks that user-defined types are parsed into DataType instead of Identifier
838842
self.parse_one("CREATE TABLE t (a udt)").this.expressions[0].args["kind"].assert_is(

0 commit comments

Comments
 (0)