From 7d1ff20b0f4a460085e9eff2a6bcc5d021c625ff Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 10 Apr 2024 10:28:28 -0400 Subject: [PATCH] improve distinct() docs differentiate more clearly between distinct() and select().distinct(). Change-Id: Id5eae749393e5898ae501b2462ec4c2c54262e2f (cherry picked from commit da639af16f77118bc17bbf5cf78fe41dd1818168) --- lib/sqlalchemy/sql/_elements_constructors.py | 21 +++++++++++++------- lib/sqlalchemy/sql/selectable.py | 21 +++++++++++++++++--- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/lib/sqlalchemy/sql/_elements_constructors.py b/lib/sqlalchemy/sql/_elements_constructors.py index 77cc2a8021..51d8ac3999 100644 --- a/lib/sqlalchemy/sql/_elements_constructors.py +++ b/lib/sqlalchemy/sql/_elements_constructors.py @@ -1090,16 +1090,23 @@ def desc( def distinct(expr: _ColumnExpressionArgument[_T]) -> UnaryExpression[_T]: """Produce an column-expression-level unary ``DISTINCT`` clause. - This applies the ``DISTINCT`` keyword to an individual column - expression, and is typically contained within an aggregate function, - as in:: + This applies the ``DISTINCT`` keyword to an **individual column + expression** (e.g. not the whole statement), and renders **specifically + in that column position**; this is used for containment within + an aggregate function, as in:: from sqlalchemy import distinct, func - stmt = select(func.count(distinct(users_table.c.name))) + stmt = select(users_table.c.id, func.count(distinct(users_table.c.name))) + + The above would produce an statement resembling:: - The above would produce an expression resembling:: + SELECT user.id, count(DISTINCT user.name) FROM user - SELECT COUNT(DISTINCT name) FROM user + .. tip:: The :func:`_sql.distinct` function does **not** apply DISTINCT + to the full SELECT statement, instead applying a DISTINCT modifier + to **individual column expressions**. For general ``SELECT DISTINCT`` + support, use the + :meth:`_sql.Select.distinct` method on :class:`_sql.Select`. The :func:`.distinct` function is also available as a column-level method, e.g. :meth:`_expression.ColumnElement.distinct`, as in:: @@ -1122,7 +1129,7 @@ def distinct(expr: _ColumnExpressionArgument[_T]) -> UnaryExpression[_T]: :data:`.func` - """ + """ # noqa: E501 return UnaryExpression._create_distinct(expr) diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py index 65978f6646..0f19810ccb 100644 --- a/lib/sqlalchemy/sql/selectable.py +++ b/lib/sqlalchemy/sql/selectable.py @@ -5972,11 +5972,26 @@ class Select( @_generative def distinct(self, *expr: _ColumnExpressionArgument[Any]) -> Self: r"""Return a new :func:`_expression.select` construct which - will apply DISTINCT to its columns clause. + will apply DISTINCT to the SELECT statement overall. + + E.g.:: + + from sqlalchemy import select + stmt = select(users_table.c.id, users_table.c.name).distinct() + + The above would produce an statement resembling:: + + SELECT DISTINCT user.id, user.name FROM user + + The method also accepts an ``*expr`` parameter which produces the + PostgreSQL dialect-specific ``DISTINCT ON`` expression. Using this + parameter on other backends which don't support this syntax will + raise an error. :param \*expr: optional column expressions. When present, - the PostgreSQL dialect will render a ``DISTINCT ON (>)`` - construct. + the PostgreSQL dialect will render a ``DISTINCT ON ()`` + construct. A deprecation warning and/or :class:`_exc.CompileError` + will be raised on other backends. .. deprecated:: 1.4 Using \*expr in other dialects is deprecated and will raise :class:`_exc.CompileError` in a future version. -- 2.47.2