Selecione valores distintos de um campo de tabela
-
20-09-2019 - |
Pergunta
Estou lutando para dar a cabeça no Orm do Django. O que eu quero fazer é obter uma lista de valores distintos dentro de um campo na minha mesa ... o equivalente a um dos seguintes:
SELECT DISTINCT myfieldname FROM mytable
(ou alternativamente)
SELECT myfieldname FROM mytable GROUP BY myfieldname
Eu pelo menos gostaria de fazê -lo o caminho do Django antes de recorrer ao SQL bruto. Por exemplo, com uma tabela:
id, rua, cidade
1, Main Street, casco
2, outra rua, casco
3, Bribble Way, Leicester
4, outra maneira, Leicester
5, High Street, Londidium
Eu gostaria de obter:
Hull, Leicester, Londidium.
Solução
Diga que seu modelo é 'loja'
class Shop(models.Model):
street = models.CharField(max_length=150)
city = models.CharField(max_length=150)
# some of your models may have explicit ordering
class Meta:
ordering = ('city')
Já que você pode ter o Meta
classe ordering
Conjunto de atributos, você pode usar order_by()
sem parâmetros para limpar qualquer pedido ao usar distinct()
. Veja a documentação em order_by
()
Se você não deseja que nenhum pedido seja aplicado a uma consulta, nem mesmo a ordem padrão, ligue para o pedido_by () sem parâmetros.
e distinct()
na nota em que discute questões usando o uso distinct()
com pedidos.
Para consultar seu banco de dados, você só precisa ligar:
models.Shop.objects.order_by().values('city').distinct()
Retorna um DictionNary
ou
models.Shop.objects.order_by().values_list('city').distinct()
Este retorna um ValuesListQuerySet
que você pode lançar para um list
. Você também pode adicionar flat=True
para values_list
Para achatar os resultados.
Veja também: Obtenha valores distintos de consulta por campo
Outras dicas
Além do ainda muito relevante Resposta de Jujule, Acho muito importante estar ciente das implicações de order_by()
sobre distinct("field_name")
Consultas. Este é, no entanto, um recurso Postgres apenas!
Se você estiver usando o Postgres e se você definir um nome de campo para o qual a consulta deve ser distinta, então order_by()
precisa começar com o mesmo nome de campo (ou nomes de campo) na mesma sequência (pode haver mais campos depois).
Observação
Quando você especifica nomes de campo, você deve fornecer um order_by () no Queryset, e os campos em ordem_by () devem começar com os campos em distintos (), na mesma ordem.
Por exemplo, selecione distinto em (a) fornece a primeira linha para cada valor na coluna a. Se você não especificar um pedido, receberá uma linha arbitrária.
Se você deseja extrair uma lista de cidades nas quais você conhece lojas, o exemplo de Jujule teria que ser adaptado a isso:
# returns an iterable Queryset of cities.
models.Shop.objects.order_by('city').values_list('city', flat=True).distinct('city')
Por exemplo:
# select distinct code from Platform where id in ( select platform__id from Build where product=p)
pl_ids = Build.objects.values('platform__id').filter(product=p)
platforms = Platform.objects.values_list('code', flat=True).filter(id__in=pl_ids).distinct('code')
platforms = list(platforms) if platforms else []