2013-02-12 3 views
10

Basit bir ileti sistemindeki bir kullanıcı etkinliği özeti içeren bir şablonu doldurmam gerekiyor. Her mesaj göndereni için gönderilen mesajların sayısını ve farklı alıcıların sayısını istiyorum. İşte SQL yaparım nasılSQL COUNT (DISTINCT <column>) Django ORM sürümü

class Message(models.Model): 
    sender = models.ForeignKey(User, related_name='messages_from') 
    recipient = models.ForeignKey(User, related_name='messages_to') 
    timestamp = models.DateTimeField(auto_now_add=True) 

:

İşte modelin basitleştirilmiş versiyonu

SELECT sender_id, COUNT(id), COUNT(DISTINCT recipient_id) 
    FROM myapp_messages 
    GROUP BY sender_id; 

ben ORM sorgular toplama belgelere yoluyla okuyordum, ve annotate() ilk COUNT sütunu ele alabilse de, COUNT (DISTINCT) sonucunu elde etmenin bir yolunu görmüyorum (hatta ekstra (select = {}) çalışmadığı gibi görünüyor). Bu bir Django ORM sorgusuna dönüştürülebilir mi yoksa sadece ham SQL ile mi çalışmalıyım?

+0

[ ' .distinct() '] (https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.distinct) filtresi olabilir e kullanışlı. –

+0

COUNT (DISTINCT recipient_id) öğesini göz ardı edersek, açıklama ve Sayma işlevi kullanılarak oldukça basittir. Burada django'nun farklı() yardımcı olmuyor. Bu iki şeyi (açıklamalı ve ayrı) bir araya getirmenin mümkün olduğunu düşünmüyorum. Sanırım iki sorgu yazmalısın. – jurgenreza

cevap

8
Sen gerçekten farklı kullanabilir ve bu cevap görüldüğü gibi, birbirine güvenebilirsiniz

:

SELECT sender_id, COUNT(id), COUNT(DISTINCT recipient_id) 
FROM myapp_messages 
GROUP BY sender_id; 

olacaktı: Senin durumunda https://stackoverflow.com/a/13145407/237091

Message.objects.values('sender').annotate(
    message_count=Count('sender'), 
    recipient_count=Count('recipient', distinct=True)) 
4
from django.db.models import Count 

messages = Message.objects.values('sender').annotate(message_count=Count('sender')) 

for m in messages: 
    m['recipient_count'] = len(Message.objects.filter(sender=m['sender']).\ 
           values_list('recipient', flat=True).distinct()) 
+0

Teşekkürler! Anladığım kadarıyla, bu durum mesaj gönderen (artı bir) olduğu kadar çok veritabanı sorgusu olacağı anlamına geliyor mu? – nephtes

+0

@nephtes Evet. Temel olarak, Count() içinde distinct() kullanmanın bir yolu olduğunu düşünmüyorum. Belki, ham sql ile daha iyi. Diğerlerinin daha iyi bir fikir ortaya atmadıkça, bunun django ile yapmanın en iyi yolu olduğunu düşünüyorum! – jurgenreza

+1

@jurgenreza (Bu yazı eski ama biliyorum ...) Daha fazla kullanmanın daha iyi bir yol olacağını düşünüyorum: Message.objects.filter (...). Extra ({'recipient_count': 'COUNT (DISTINCT recipient_id) '}). değerleri (' recipient_count '). Ekstra dokümanlar: https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.extra – paperreduction

İlgili konular