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 ORDER BY
expresión silencia el error, pero realmente no quiero agregar la clasificación address_id
. ¿Es posible hacerlo sin ordenar por address_id
?
sql
postgresql
sql-order-by
distinct-on
sl_bug
fuente
fuente
Respuestas:
La documentación dice:
Documentación oficial
Entonces tendrás que agregar el
address_id
al orden por.Alternativamente, si está buscando la fila completa que contiene el producto comprado más reciente para cada uno
address_id
y ese resultado ordenado porpurchased_at
entonces, está tratando de resolver el mayor problema de N por grupo que se puede resolver mediante los siguientes enfoques:La solución general que debería funcionar en la mayoría de los DBMS:
Una solución más orientada a PostgreSQL basada en la respuesta de @ hkf:
Problema aclarado, extendido y resuelto aquí: selección de filas ordenadas por una columna y distintas en otra
fuente
SELECT DISTINCT ON (purchases.purchased_at, address_id)
. Sin embargo, dos registros con la misma dirección_id pero diferentes valores adquiridos_at generarán duplicados en el conjunto devuelto. Asegúrese de conocer los datos que está consultando.Puede ordenar por address_id en una subconsulta, luego ordenar por lo que desee en una consulta externa.
fuente
select
, ¿no creo que este es un código de producción?address_id
dos veces (sin necesidad). Muchos clientes tienen problemas con nombres de columnas duplicados.ORDER BY address_id DESC
Es inútil y engañoso. No hace nada útil en esta consulta. El resultado es una selección arbitraria de cada conjunto de filas con el mismoaddress_id
, no la fila con la últimapurchased_at
. La pregunta ambigua no lo solicitó explícitamente, pero esa es casi seguramente la intención del OP. En resumen: no use esta consulta . Publiqué alternativas con explicación.Una subconsulta puede resolverlo:
Las expresiones iniciales en
ORDER BY
tienen que estar de acuerdo con las columnasDISTINCT ON
, por lo que no puede ordenar por diferentes columnas en el mismoSELECT
.Solo use un adicional
ORDER BY
en la subconsulta si desea elegir una fila particular de cada conjunto:Si
purchased_at
puede serNULL
, considereDESC NULLS LAST
. Pero asegúrese de que coincida con su índice si tiene la intención de usarlo. Ver:Relacionado, con más explicaciones:
fuente
DISTINCT ON
sin una coincidenciaORDER BY
. La primera consulta requiere unORDER BY address_id
dentro de la subconsulta.DISTINCT ON
sinORDER BY
en la misma consulta. Obtiene una fila arbitraria de cada conjunto de pares definidos por laDISTINCT ON
cláusula en este caso. Pruébelo o siga los enlaces anteriores para obtener detalles y enlaces al manual.ORDER BY
en la misma consulta (la mismaSELECT
) simplemente no puede estar en desacuerdo conDISTINCT ON
. Yo también expliqué eso.ORDER BY
nota "impredecible a menos que se use" en los documentos porque no tiene sentido para mí que la función esté implementada para poder manejar conjuntos de valores no consecutivos ... pero no te permitirá explotar eso con un orden explícito. Molesto.DISTINCT ON
expresiones (todavía).La función de ventana puede resolver eso de una sola vez:
fuente
address_id
. Sin embargo, el principio podría funcionar. Ejemplos relacionados: stackoverflow.com/a/22064571/939860 o stackoverflow.com/a/11533808/939860 . Pero hay consultas más cortas y / o más rápidas para el problema en cuestión.Para cualquiera que use Flask-SQLAlchemy, esto funcionó para mí
fuente
query.distinct(foo).from_self().order(bar)
Purchases.query
?También puede hacerlo utilizando la cláusula group by
fuente
purchases
solo tenga las dos columnasaddress_id
ypurchased_at
). Debido a estoGROUP BY
, necesitará usar una función agregada para obtener el valor de cada columna que no se usa para agrupar, por lo que todos los valores provendrán de diferentes filas del grupo a menos que pase por una gimnasia fea e ineficiente. Esto solo se puede solucionar mediante el uso de funciones de ventana en lugar deGROUP BY
.