2013-02-12 17 views
10

単純なメッセージングシステムでは、ユーザーアクティビティの概要をテンプレートに記入する必要があります。各メッセージ送信者には、送信されるメッセージの数と個別の受信者の数が必要です。ここで私はSQLでそれを行うだろう方法ですDjango ORMバージョンのSQL COUNT(DISTINCT <column>)

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) 

はここでモデルの簡易版です

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

私はORMクエリで集計上のドキュメントを読んされてきました、 annotate()は最初のCOUNT列を処理できますが、COUNT(DISTINCT)の結果を得る方法はありません(余分な(select = {})は動作していません。これはDjangoのORMクエリに変換できますか、それとも生のSQLを使用するだけですか?

+0

[ ' .distinct() '](https://docs.djangoproject.com/ja/dev/ref/models/querysets/#django.db.models.query.QuerySet.distinct)filter might com eを手軽に。 –

+0

COUNT(DISTINCT recipient_id)を無視すると、annotateとCount関数を使用するとかなり簡単になります。ここで、djangoのdistinct()は役に立ちません。私は、これらの2つのもの(注釈と別名)を統合することは可能ではないと考えています。あなたは私が推測する2つのクエリを書く必要があります。 – jurgenreza

答えて

8
あなたは確かに明確な使用と、この答えに見られるように、一緒にカウントすることができ

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

になるでしょう:あなたのケースでは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

ありがとう!これは、メッセージの送信者(1つに加えて)と同じくらい多くのデータベースクエリが存在するということを理解していますか? – nephtes

+0

@nephtesはい。基本的には、Count()内でdistinct()を使う方法はないと思います。たぶん、あなたは生のSQLで良いです。私はこれが他の人がより良いアイデアを思い付かない限り、ジャンゴでそれを行うための最良の方法だと思う! – jurgenreza

+1

@jurgenreza(私はこの投稿が古いと知っていますが...)私は、より良い方法は、余分なものを使用することだと思います:Message.objects.filter(...)extra({'recipient_count': 'COUNT(DISTINCT recipient_id) '}))values(' recipient_count ')。余分なドキュメント:https://docs.djangoproject.com/ja/dev/ref/models/querysets/#django.db.models.query.QuerySet.extra – paperreduction