must multiple initial expressions columns sql postgresql sql-order-by distinct-on

sql - multiple - django select distinct on expressions must match initial order by expressions



PostgreSQL DISTINCT ON con diferentes ORDER BY (6)

La documentación dice:

DISTINCT ON (expresión [, ...]) mantiene solo la primera fila de cada conjunto de filas donde las expresiones dadas son iguales. [...] Tenga en cuenta que la "primera fila" de cada conjunto es impredecible a menos que se utilice ORDER BY para garantizar que la fila deseada aparezca primero. [...] Las expresiones DISTINCT ON deben coincidir con la (s) expresión (es) ORDER BY más a la izquierda.

Documentación oficial

Por lo tanto, tendrá que agregar la address_id al pedido por.

Alternativamente, si está buscando la fila completa que contiene el producto comprado más reciente para cada address_id y ese resultado ordenado por purchased_at entonces está tratando de resolver un mayor problema de N por grupo que puede resolverse mediante los siguientes enfoques:

La solución general que debería funcionar en la mayoría de los DBMS:

SELECT t1.* FROM purchases t1 JOIN ( SELECT address_id, max(purchased_at) max_purchased_at FROM purchases WHERE product_id = 1 GROUP BY address_id ) t2 ON t1.address_id = t2.address_id AND t1.purchased_at = t2.max_purchased_at ORDER BY t1.purchased_at DESC

Una solución más orientada a PostgreSQL basada en la respuesta de @ hkf:

SELECT * FROM ( SELECT DISTINCT ON (address_id) * FROM purchases WHERE product_id = 1 ORDER BY address_id, purchased_at DESC ) t ORDER BY purchased_at DESC

Problema aclarado, extendido y resuelto aquí: Selección de filas ordenadas por una columna y distintas en otra

Quiero ejecutar esta consulta:

SELECT DISTINCT ON (address_id) purchases.address_id, purchases.* FROM purchases WHERE purchases.product_id = 1 ORDER BY purchases.purchased_at DESC

Pero me sale este error:

PG :: Error: ERROR: las expresiones SELECT DISTINCT ON deben coincidir con las expresiones ORDER BY iniciales

Agregar address_id como primera expresión ORDER BY silencia el error, pero realmente no quiero agregar sorting sobre address_id . ¿Es posible hacer sin ordenar por address_id ?


La función de ventana puede resolver eso en una pasada:

SELECT DISTINCT ON (address_id) LAST_VALUE(purchases.address_id) OVER wnd AS address_id FROM "purchases" WHERE "purchases"."product_id" = 1 WINDOW wnd AS ( PARTITION BY address_id ORDER BY purchases.purchased_at DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)


Para cualquiera que use Flask-SQLAlchemy, esto funcionó para mí

from app import db from app.models import Purchases from sqlalchemy.orm import aliased from sqlalchemy import desc stmt = Purchases.query.distinct(Purchases.address_id).subquery(''purchases'') alias = aliased(Purchases, stmt) distinct = db.session.query(alias) distinct.order_by(desc(alias.purchased_at))


Puede ordenar por dirección_id en una subconsulta, luego ordenar según lo que desee en una consulta externa.

SELECT * FROM (SELECT DISTINCT ON (address_id) purchases.address_id, purchases.* FROM "purchases" WHERE "purchases"."product_id" = 1 ORDER BY address_id DESC ) ORDER BY purchased_at DESC


También puedes hacer esto usando la cláusula group by

SELECT purchases.address_id, purchases.* FROM "purchases" WHERE "purchases"."product_id" = 1 GROUP BY address_id, purchases.purchased_at ORDER purchases.purchased_at DESC


Una subconsulta puede resolverlo:

SELECT * FROM ( SELECT DISTINCT ON (address_id) * FROM purchases WHERE product_id = 1 ) p ORDER BY purchased_at DESC;

Las expresiones principales en ORDER BY deben estar de acuerdo con las columnas en DISTINCT ON , por lo que no puede ordenar por columnas diferentes en el mismo SELECT .

Solo use un ORDER BY adicional en la subconsulta si desea seleccionar una fila particular de cada conjunto:

SELECT * FROM ( SELECT DISTINCT ON (address_id) * FROM purchases WHERE product_id = 1 ORDER BY address_id, purchased_at DESC -- get "latest" row per address_id ) p ORDER BY purchased_at DESC;

Si purchased_at puede ser NULL , considere DESC NULLS LAST .
Relacionado, con más explicaciones: