20

我在我的views.py

Message.objects.raw('''
        SELECT s1.ID, s1.CHARACTER_ID, MAX(s1.MESSAGE) MESSAGE, MAX(s1.c) occurrences
        FROM
           (SELECT ID, CHARACTER_ID, MESSAGE, COUNT(*) c
            FROM tbl_message WHERE ts > DATE_SUB(NOW(), INTERVAL %s DAY) GROUP BY CHARACTER_ID,MESSAGE) s1
        LEFT JOIN
           (SELECT ID, CHARACTER_ID, MESSAGE, COUNT(*) c
            FROM tbl_message WHERE ts > DATE_SUB(NOW(), INTERVAL %s DAY) GROUP BY CHARACTER_ID,MESSAGE) s2
          ON s1.CHARACTER_ID=s2.CHARACTER_ID
         AND s1.c < s2.c
        WHERE s2.c IS NULL
        GROUP BY CHARACTER_ID
        ORDER BY occurrences DESC''', [days, days])

此 SQL 语句的结果(直接在数据库上测试)是:

ID  | CHARACTER_ID | MESSAGE | OCCURENCES
----+--------------+---------+--------------
148 | 10           | test    | 133

但我得到的只是InvalidQuery信息的例外Raw query must include the primary key

然后我仔细检查了文档并阅读:

只有一个字段不能省略 - 主键字段....如果您忘记包含主键,则会引发 InvalidQuery 异常。

如您所见,我在语句中添加了请求的主键。怎么了?

class Message(models.Model):
    character = models.ForeignKey('Character')
    message = models.TextField()
    location = models.ForeignKey('Location')
    ts = models.DateTimeField()

    class Meta:
        pass

    def __unicode__(self):
        return u'%s: %s...' % (self.character, self.message[0:20])
4

4 回答 4

24

在查询中包含 1 作为 id

Message.objects.raw('''
        SELECT 1 as id , s1.ID, s1.CHARACTER_ID, MAX(s1.MESSAGE) MESSAGE, MAX(s1.c) occurrences
        FROM
           (SELECT ID, CHARACTER_ID, MESSAGE, COUNT(*) c
            FROM tbl_message WHERE ts > DATE_SUB(NOW(), INTERVAL %s DAY) GROUP BY CHARACTER_ID,MESSAGE) s1
        LEFT JOIN
           (SELECT ID, CHARACTER_ID, MESSAGE, COUNT(*) c
            FROM tbl_message WHERE ts > DATE_SUB(NOW(), INTERVAL %s DAY) GROUP BY CHARACTER_ID,MESSAGE) s2
          ON s1.CHARACTER_ID=s2.CHARACTER_ID
         AND s1.c < s2.c
        WHERE s2.c IS NULL
        GROUP BY CHARACTER_ID
        ORDER BY occurrences DESC''', [days, days]) 
于 2017-02-03T08:50:01.830 回答
16

我使用 Python 2.7.5、Django 1.5.1 和 Mysql 5.5 重现了同样的问题。

我已经保存了对变量的raw调用结果,所以我可以检查它包含哪些列:results

>>> results.columns
['ID', 'CHARACTER_ID', 'MESSAGE', 'occurrences']

ID是大写的,所以在你的查询中我改为s1.ID并且s1.id它有效:

>>> results = Message.objects.raw('''
...         SELECT s1.id, s1.CHARACTER_ID, MAX(s1.MESSAGE) MESSAGE, MAX(s1.c) occurrences
...         FROM
...            (SELECT ID, CHARACTER_ID, MESSAGE, COUNT(*) c
...             FROM tbl_message WHERE ts > DATE_SUB(NOW(), INTERVAL %s DAY) GROUP BY CHARACTER_ID,MESSAGE) s1
...         LEFT JOIN
...            (SELECT ID, CHARACTER_ID, MESSAGE, COUNT(*) c
...             FROM tbl_message WHERE ts > DATE_SUB(NOW(), INTERVAL %s DAY) GROUP BY CHARACTER_ID,MESSAGE) s2
...           ON s1.CHARACTER_ID=s2.CHARACTER_ID
...          AND s1.c < s2.c
...         WHERE s2.c IS NULL
...         GROUP BY CHARACTER_ID
...         ORDER BY occurrences DESC''', [days, days])
>>> results.columns
['id', 'CHARACTER_ID', 'MESSAGE', 'occurrences']
>>> results[0]
<Message_Deferred_character_id_location_id_message_ts: Character object: hello...>
于 2013-08-12T00:33:09.830 回答
3

确保主键是 select 语句的一部分。

例子:

这将不起作用:

`Model.objects.raw("Select Min(id), rider_id from Table_Name group by rider_id")`

但这会起作用:

`Model.objects.raw("Select id, Min(id), rider_id from Table_Name group by rider_id")`
于 2021-10-08T11:52:53.293 回答
1

对于那些也遇到这个问题的人,也许像我一样,想知道为什么 Django 需要 a pk,当你没有pk查询时(例如你想要多行)——Django 只需要id返回一个字段,pk不需要是一部分的一个where条款。IE:

select * from table where foo = 'bar';

或者

select id, description from table where foo = 'bar';

如果表中有字段,这两种方法都有效id。但这会引发 Thomas Schwärzl 描述的错误,因为没有id返回任何字段:

select description from table where foo = 'bar';

于 2021-03-29T22:11:55.250 回答