2013-06-27 11 views
6

ich eine rohe SQL-Anweisung bekam in views.pyRaw Abfrage muss der Primärschlüssel enthalten

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

Das Ergebnis dieser SQL-Anweisung (auf Datenbank getestet direkt) ist:

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

Aber alles, was ich Erhaltenes ist ein InvalidQuery Ausnahme mit den Informationen Raw query must include the primary key

dann doppelt ich die docs geprüft und las:

Es gibt nur ein Feld, das Sie nicht auslassen können - den Primärschlüssel Feld .... Eine InvalidQuery-Ausnahme wird ausgelöst, wenn Sie den Primärschlüssel vergessen haben.

Wie Sie sehen können, habe ich den angeforderten Primärschlüssel in meiner Anweisung hinzugefügt. Was ist los mit dir?

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]) 
+0

Haben Sie dieses Problem immer noch? – dusan

+0

Ich habe einen Workaround mit Aussicht ... aber wenn Sie eine Lösung haben, zögern Sie nicht, es zu posten. – Thomas

+0

Können Sie Ihr 'Message' Modell posten? – dusan

Antwort

8

ich reproduziert das gleiche Problem mit Python 2.7.5, Django 1.5.1 und Mysql 5.5.

Ich habe das Ergebnis des raw Aufrufs den results Variable gespeichert, ich kann so überprüfen, welche Spalten enthält:

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

ID in Groß ist, so in der Abfrage geändert ich s1.ID-s1.id und es funktioniert:

>>> 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...> 
+1

gut gemacht Herr, gut gemacht – Thomas

3

1 als ID Fügen sie auf Ihre Anfrage

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]) 
Verwandte Themen