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')
)

这样做的好处是只运行一个查询。您的查询将如下所示:

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 回答