4

私は次のモデルを持っています:

class Message(Model):
    url = URLField("URL")
    email = EmailField("E-Mail")
    contacted = BooleanField("Contacted", default=False)

次のようなデータの例:

| url | email           | contacted |
+-----+-----------------+-----------+
| foo | foo@example.com | N         |
| bar | bar@example.com | N         |
| baz | foo@example.com | Y         |

電子メールアドレスに連絡したことがないすべての個別の行を(電子メールアドレスで)選択したいと思います。このサンプルデータでは、bar@example.com返されるのは行だけです。

4

2 に答える 2

2

これにより、必要なレコードが返されます。

not_contacted = Message.objects.exclude(
    email__in=Message.objects.filter(contacted=True).values('email')
)

これには、1つのクエリのみを実行するという利点があります。クエリは次のようになります。

SELECT
    messages_message.id, messages_message.url, messages_message.email, messages_message.contacted
FROM
    Messages
WHERE NOT
    (messages_message.email IN
        ( SELECT U0.email from messages_message U0 WHERE U0.contacted = True )
    )

多くの場合、このクエリは最適ではない可能性がありますが、ほとんどの用途で機能する可能性があることに注意してください。

于 2012-09-12T18:09:41.453 に答える
1
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;

CREATE TABLE massage
        ( zurl varchar NOT NULL
        , zemail varchar NOT NULL
        , contacted boolean
        );
INSERT into massage(zurl, zemail, contacted) VALUES

( 'foo', 'foo@example.com', False)
,( 'bar', 'bar@example.com', False)
,( 'baz', 'foo@example.com', True)
        ;

SELECT
        DISTINCT zemail AS zemail
        , MIN(zurl) AS zurl
FROM massage m
WHERE NOT EXISTS (
        SELECT *
        FROM massage nx
        WHERE nx.zemail = m.zemail
        AND nx.contacted = True
        )
GROUP BY zemail;

特定の電子メールアドレスに複数のレコードがある場合、上記のレコードは「最も低い」URLを持つレコードを選択します。それらすべてが必要な場合、クエリはさらに簡単になります。

SELECT m.zurl, m.zemail
FROM massage m
WHERE NOT EXISTS (
        SELECT *
        FROM massage nx
        WHERE nx.zemail = m.zemail
        AND nx.contacted = True
        ) ;
于 2012-09-12T16:36:28.737 に答える