Eu quero executar esta consulta:
SELECT DISTINCT ON (address_id) purchases.address_id, purchases.*
FROM purchases
WHERE purchases.product_id = 1
ORDER BY purchases.purchased_at DESC
Mas eu recebo este erro:
PG :: Erro: ERRO: As expressões SELECT DISTINCT ON devem corresponder às expressões ORDER BY iniciais
A adição address_id
como primeira ORDER BY
expressão silencia o erro, mas eu realmente não quero adicionar a classificação address_id
. É possível fazer sem pedir address_id
?
sql
postgresql
sql-order-by
distinct-on
sl_bug
fonte
fonte
Respostas:
A documentação diz:
Documentação oficial
Então você terá que adicionar o
address_id
ao pedido por.Como alternativa, se você estiver procurando a linha completa que contém o produto comprado mais recente para cada um
address_id
e o resultado classificado porpurchased_at
então está tentando resolver o maior problema de N por grupo que pode ser resolvido pelas seguintes abordagens:A solução geral que deve funcionar na maioria dos DBMSs:
Uma solução mais orientada para o PostgreSQL baseada na resposta da @ hkf:
Problema esclarecido, estendido e resolvido aqui: Selecionando linhas ordenadas por alguma coluna e distintas em outra
fonte
SELECT DISTINCT ON (purchases.purchased_at, address_id)
. No entanto, dois registros com o mesmo endereço_id, mas com valores diferentes de purchase_at resultarão em duplicatas no conjunto retornado. Verifique se você conhece os dados que está consultando.Você pode solicitar por address_id em uma subconsulta e depois pelo que deseja em uma consulta externa.
fonte
select
, não acho que seja um código de produção?address_id
duas vezes (sem necessidade). Muitos clientes têm problemas com nomes de colunas duplicados.ORDER BY address_id DESC
é inútil e enganoso. Não faz nada útil nesta consulta. O resultado é uma seleção arbitrária de cada conjunto de linhas com o mesmoaddress_id
, não da linha com a mais recentepurchased_at
. A pergunta ambígua não pediu isso explicitamente, mas essa é quase certamente a intenção do OP. Em resumo: não use esta consulta . Postei alternativas com explicações.Uma subconsulta pode resolvê-lo:
As expressões iniciais em
ORDER BY
precisam concordar com as colunasDISTINCT ON
, portanto, você não pode ordenar por colunas diferentes na mesmaSELECT
.Use apenas um adicional
ORDER BY
na subconsulta se desejar escolher uma linha específica de cada conjunto:Se
purchased_at
puderNULL
, considereDESC NULLS LAST
. Mas certifique-se de corresponder ao seu índice, se você pretende usá-lo. Vejo:Relacionado, com mais explicações:
fonte
DISTINCT ON
sem uma correspondênciaORDER BY
. A primeira consulta requer umaORDER BY address_id
dentro da subconsulta.DISTINCT ON
semORDER BY
na mesma consulta. Você obtém uma linha arbitrária de cada conjunto de pares definido pelaDISTINCT ON
cláusula nesse caso. Experimente ou siga os links acima para obter detalhes e links para o manual.ORDER BY
na mesma consulta (o mesmoSELECT
) simplesmente não pode discordarDISTINCT ON
. Eu expliquei isso também.ORDER BY
nota "imprevisível, a menos que seja usado" nos documentos, porque não faz sentido para mim que o recurso seja implementado para poder lidar com conjuntos de valores não consecutivos ... mas não permitirá que você explorar isso com uma ordem explícita. Irritante.DISTINCT ON
expressões.A função Window pode resolver isso de uma só vez:
fonte
address_id
. O princípio poderia funcionar, no entanto. Exemplos relacionados: stackoverflow.com/a/22064571/939860 ou stackoverflow.com/a/11533808/939860 . Mas existem consultas mais curtas e / ou mais rápidas para o problema em questão.Para quem usa o Flask-SQLAlchemy, isso funcionou para mim
fonte
query.distinct(foo).from_self().order(bar)
Purchases.query
?Você também pode fazer isso usando a cláusula group by
fonte
purchases
tenha apenas as duas colunasaddress_id
epurchased_at
). Por issoGROUP BY
, você precisará usar uma função agregada para obter o valor de cada coluna não usada para agrupamento, para que todos os valores sejam provenientes de linhas diferentes do grupo, a menos que você pratique uma ginástica feia e ineficiente. Isso pode ser corrigido apenas usando as funções da janela em vez deGROUP BY
.