1

Django アプリには、'Proposal'、'ProposalRevision'、'Opinion'、'User' の 4 つのモデルがあります。簡単な定義は次のとおりです。

class User(models.Model):
    pass

class Proposal(models.Model):
    pass

class ProposalRevision(models.Model):
    proposal = models.ForeignKey(Proposal)
    created = models.DateTimeField()

class Opinion(models.Model):
    user = models.ForeignKey(User)
    proposal = models.ForeignKey(Proposal)
    created = models.DateTimeField()

各提案には多くの改訂が含まれる場合があります。ユーザーは、特定の提案に対して多くの意見を持っている場合があります。私が作りたいクエリは次のとおりです。

最後の提案リビジョンが作成されてから特定のユーザーが意見を残していないすべての提案を取得します。

アプリケーションのユースケースは、意見を残す必要がある提案をユーザーに示したいというものです。

素朴に、私はこの方法でクエリを行うことを考えました:

Proposal.objects.annotate(
        latest_revision=Max('proposalrevision__created')
    ).exclude(
        opinion__user=user,
        opinion__created__lte=F('latest_revision')
    )

ただし、これは機能しません。これは、F 式が集計で機能しないためです (まだ)。

「余分な」クエリでこれを回避するために、必要なクエリを実行するバニラ SQL を書き始めましたが、「where」句で集計を使用することに行き詰まりました。私が扱っているSQLは次のようになります。

SELECT ...snip..., MAX("proposal_proposalrevision"."created") as "latest_revision"
FROM "proposal_proposal"
LEFT OUTER JOIN "proposal_proposalrevision" ON
    ("proposal_proposal"."id" = "proposal_proposalrevision"."proposal_id")
WHERE "proposal_proposal"."id" NOT IN (
    SELECT (U1."proposal_id") FROM "proposal_opinion" U1
    WHERE (
        U1."user_id" = 1 AND U1."proposal_id" IS NOT NULL AND
        U1."created" > "latest_proposal"
    )
)
GROUP BY ...snip...

SQLite でエラー " misuse of aggregate: MAX()" が表示されます。これは、変数名 " latest_proposal" を使用するか、集計関数の繰り返しに置き換えるかに関係なく保持されますMAX("proposal_proposalrevision"."created")

集計を使用して返されたセットをフィルタリングするために、このクエリを作成するにはどうすればよいでしょうか?

4

1 に答える 1

1

この解決策を試してください:

SELECT a.*, b.maxrevisiondate AS latest_revision
FROM proposal_proposal a
LEFT JOIN
(
    SELECT proposal_id, MAX(created) AS maxrevisiondate
    FROM proposal_proposalrevision
    GROUP BY proposal_id
) b ON a.id = b.proposal_id
LEFT JOIN proposal_opinion c ON
    a.id = c.proposal_id AND
    (b.maxrevisiondate IS NULL OR c.created > b.maxrevisiondate) AND
    c.user_id = <user_id here>
WHERE c.proposal_id IS NULL 
于 2012-07-12T22:10:09.247 に答える