2016-04-01 11 views
0

Ich muss einen Join über 4 Tabellen machen, während die maximale (d. H. Neueste) Zeitmarke des Tests zur Verknüpfung mit einer Person auswählen. Für jeden Schüler in einer Klasse, möchte ich Lookup, was ihre letzten Tests ist, und erhalten ihre ID und ZeitstempelKomplizierte Join und MAX() Abfrage in MySQL

SELECT students.ref, 
     students.fname, 
     students.sname, 
     classes.name AS 'group', 
     tests.id, 
     max(tests.timestamp) 
FROM tests, students, classlinks, classes 
WHERE tests.ref=students.ref AND 
     classlinks.ref=students.ref AND 
     classlinks.classid=29 AND 
     tests.grade=2 AND 
     tests.subject=2 
GROUP BY students.ref 
ORDER BY students.sname ASC, students.fname ASC 

sieht wie es perfekt ist: für jeden Schüler in einer Klasse, gibt es den Zeitstempel von ihrem letzten Test. Leider ist die diesem Zeitstempel zugeordnete Test-ID falsch: Sie gibt nur die Test-ID eines Zufallstests an.

Wenn ich die ‚Gruppe‘ ändern

GROUP BY students.ref, tests.id 

dann die Abfrage richtigen Test sein IDs übereinstimmt Zeitstempel zu korrigieren, aber jetzt gibt es für jeden Schüler mehr Einträge. Hat jemand einen Rat, so dass ich für jeden Schüler eine Zeile bekommen kann, mit korrekter Test-ID, die mit dem letzten Zeitstempel übereinstimmt? Jede Hilfe wird geschätzt. Vielen Dank.

Tabellenbeschreibungen:

mysql> describe students; 
+--------+-------------+------+-----+---------+----------------+ 
| Field | Type  | Null | Key | Default | Extra   | 
+--------+-------------+------+-----+---------+----------------+ 
| id  | int(11)  | NO | PRI | NULL | auto_increment | 
| ref | varchar(50) | NO | UNI | NULL |    | 
| fname | varchar(22) | NO |  | NULL |    | 
| sname | varchar(22) | NO |  | NULL |    | 
| school | int(11)  | NO |  | NULL |    | 
| year | int(11)  | NO |  | NULL |    | 
+--------+-------------+------+-----+---------+----------------+ 
6 rows in set (0.00 sec) 
mysql> describe classes; 
+---------+-------------+------+-----+---------+----------------+ 
| Field | Type  | Null | Key | Default | Extra   | 
+---------+-------------+------+-----+---------+----------------+ 
| id  | int(11)  | NO | PRI | NULL | auto_increment | 
| subject | int(11)  | YES | MUL | NULL |    | 
| type | int(11)  | YES |  | 1  |    | 
| school | int(11)  | YES |  | NULL |    | 
| year | int(11)  | YES |  | NULL |    | 
| name | varchar(50) | YES |  | NULL |    | 
+---------+-------------+------+-----+---------+----------------+ 
6 rows in set (0.00 sec) 

mysql> describe classlinks; 
+---------+-------------+------+-----+---------+----------------+ 
| Field | Type  | Null | Key | Default | Extra   | 
+---------+-------------+------+-----+---------+----------------+ 
| id  | int(11)  | NO | PRI | NULL | auto_increment | 
| ref  | varchar(50) | YES | MUL | NULL |    | 
| subject | int(11)  | YES |  | NULL |    | 
| school | int(11)  | YES |  | NULL |    | 
| classid | int(11)  | YES | MUL | NULL |    | 
| type | int(11)  | YES |  | 1  |    | 
+---------+-------------+------+-----+---------+----------------+ 
6 rows in set (0.00 sec) 
mysql> describe tests; 
+------------+-------------+------+-----+-------------------+-----------------------------+ 
| Field  | Type  | Null | Key | Default   | Extra      | 
+------------+-------------+------+-----+-------------------+-----------------------------+ 
| id   | int(11)  | NO | PRI | NULL    | auto_increment    | 
| subject | int(11)  | YES |  | NULL    |        | 
| ref  | varchar(22) | NO | MUL | NULL    |        | 
| test  | int(3)  | NO |  | NULL    |        | 
| grade  | varchar(22) | NO |  | NULL    |        | 
| timestamp | timestamp | NO | MUL | CURRENT_TIMESTAMP |        | 
| lastupdate | timestamp | NO |  | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | 
+1

'classlinks.classid = 29 und classlinks.classid = classes.id', was ist der Sinn überprüfen funktioniert? Ein Feld kann nur einen Wert haben, also könnte das nur funktionieren, wenn die Klasse classes.id bereits 29 ist. –

+0

thanks; in Beispielabfrage korrigiert. Problem bleibt noch! – tornadof3

+0

posten Sie bitte Ihr Tabellenschema – geeksal

Antwort

1

Ich gehe davon aus, dass die Kombination von (ref,timestamp) in tests Tabelle eindeutig ist. Hier ist meine Lösung, aber ich habe keine Ihrer Beispieldaten, um es zu überprüfen. Wenn es falsch ist, eine Probe Daten zu posten, so dass ich es testen kann.

UPDATE

Hier wird die Update-Abfrage, die die diese sqlfiddle

SELECT students.ref, 
    students.fname, 
    students.sname, 
    classes.name AS 'group', 
    tests.id, 
    T.timestamp 
FROM (select ref,max(timestamp) as timestamp from tests group by ref)as T 
    natural join tests, students, classlinks, classes 
WHERE 
T.ref=students.ref AND 
classlinks.ref=students.ref AND 
classlinks.classid=classes.id AND 
classlinks.classid=29 AND 
tests.grade=2 AND 
tests.subject=2 
ORDER BY students.sname ASC, students.fname ASC 
+0

Vielen Dank für diese Antwort. Es hat eine Weile gedauert, bis ich herausgefunden habe, wie man sqlfiddle benutzt, aber ich habe hier eine erstellt: http://sqlfiddle.com/#!9/b0b698/1 Es gibt einen leichten Syntaxfehler, aber ich kann nicht Finde heraus, was es ist? – tornadof3

+0

@ Tornadof3 Überprüfen Sie die aktualisierte Antwort Ich denke, es ist endlich vorbei :) – geeksal

+0

Vielen Dank! Das funktioniert perfekt! (für mich) eine wirklich komplizierte SQL-Abfrage. – tornadof3

0

die Logik in SQL die Abfrage verwenden kann wie folgt geschrieben werden, nicht sicher mySQL aber die Logik arbeitet hoffen.

Select ref 
     ,fname 
     ,sname 
     ,ID 
     ,group 
     ,Timestamp 

From 
    (select 
     S.ref 
     ,S.fname 
     ,S.sname, 
     ,T.id 
     ,classes.name AS 'group' 
     ,T.timestamp 
     from 
      tests T,students S, classlinks, classes 
     Where 
      T.ref=S.ref and 
      T.grade=2 AND 
      classlinks.ref=students.ref AND 
      classlinks.classid=29 AND 
      classlinks.classid=classes.id AND 
      T.subject=2) A 

    inner join 

    (SELECT tests.ref   
      ,max(tests.timestamp) 
    FROM 
     tests 
    group by 
     tests.ref 
    ) B 
    on 
     A.ref=b.ref and 
     A.timestamp = b.timestamp 
+0

Hat nicht überprüft, dass Ihre Tabelle Schema, bis ich meine Antwort ... – Dev