MySQL "Gruppieren nach" und "Bestellen nach"



Answers

Hier ist ein Ansatz:

SELECT cur.textID, cur.fromEmail, cur.subject, 
     cur.timestamp, cur.read
FROM incomingEmails cur
LEFT JOIN incomingEmails next
    on cur.fromEmail = next.fromEmail
    and cur.timestamp < next.timestamp
WHERE next.timestamp is null
and cur.toUserID = '$userID' 
ORDER BY LOWER(cur.fromEmail)

Im Grunde treten Sie der Tabelle bei und suchen nach späteren Zeilen. In der where-Klausel geben Sie an, dass es keine späteren Zeilen geben darf. Dies gibt Ihnen nur die letzte Zeile.

Wenn es mehrere E-Mails mit demselben Zeitstempel geben kann, müsste diese Abfrage verfeinert werden. Wenn eine inkrementelle ID-Spalte in der E-Mail-Tabelle vorhanden ist, ändern Sie den JOIN wie folgt:

LEFT JOIN incomingEmails next
    on cur.fromEmail = next.fromEmail
    and cur.id < next.id
Question

Ich möchte in der Lage sein, eine Reihe von Zeilen aus einer Tabelle von E-Mails auszuwählen und sie nach dem Absender zu gruppieren. Meine Abfrage sieht so aus:

SELECT 
    `timestamp`, `fromEmail`, `subject`
FROM `incomingEmails` 
GROUP BY LOWER(`fromEmail`) 
ORDER BY `timestamp` DESC

Die Abfrage funktioniert fast so, wie ich es möchte - sie wählt Datensätze aus, die nach E-Mail gruppiert sind. Das Problem besteht darin, dass der Betreff und der Zeitstempel nicht dem neuesten Datensatz für eine bestimmte E-Mail-Adresse entsprechen.

Zum Beispiel könnte es zurückkehren:

fromEmail: john@example.com, subject: hello
fromEmail: mark@example.com, subject: welcome

Wenn die Datensätze in der Datenbank sind:

fromEmail: john@example.com, subject: hello
fromEmail: john@example.com, subject: programming question
fromEmail: mark@example.com, subject: welcome

Wenn der Betreff "Programmierfrage" der neueste ist, wie kann ich diesen Datensatz beim Gruppieren der E-Mails auswählen?




Gemäß dem SQL-Standard können Sie keine nicht aggregierten Spalten in der Auswahlliste verwenden. MySQL erlaubt solche Verwendung (Uless ONLY_FULL_GROUP_BY Modus verwendet), aber das Ergebnis ist nicht vorhersehbar.

ONLY_FULL_GROUP_BY

Sie sollten zuerst aus E-Mail, MIN (lesen) und dann mit zweiter Abfrage (oder Unterabfrage) - Betreff auswählen.




Ich kämpfte mit diesen beiden Ansätzen für komplexere Abfragen als die gezeigten, weil der Unterabfrage-Ansatz schrecklich ineffizient war, egal, welche Indizes ich anlegte, und weil ich den äußeren Self-Join nicht durch Hibernate erreichen konnte

Der beste (und einfachste) Weg, dies zu tun, besteht darin, nach etwas zu gruppieren, das so konstruiert ist, dass es eine Verkettung der von Ihnen benötigten Felder enthält und sie dann mithilfe von Ausdrücken in der SELECT-Klausel herauszieht. Wenn Sie eine MAX () -Methode ausführen müssen, stellen Sie sicher, dass das Feld, für das Sie MAX () überschreiben möchten, immer am signifikantesten Ende der verketteten Entität liegt.

Der Schlüssel zum Verständnis ist, dass die Abfrage nur Sinn ergeben kann, wenn diese anderen Felder für jede Entität, die die Max () erfüllt, invariant sind, so dass die anderen Teile der Verkettung hinsichtlich der Sortierung ignoriert werden können. Es wird erklärt, wie dies am Ende dieser Verknüpfung zu tun ist. http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html

Wenn Sie ein insert / update-Ereignis (wie einen Trigger) erhalten, um die Verkettung der Felder vorzuberechnen, können Sie es indizieren und die Abfrage wird so schnell sein, als wäre die Gruppe vorbei nur das Feld, das Sie eigentlich MAX wollten ( ). Sie können es sogar verwenden, um das Maximum von mehreren Feldern zu erhalten. Ich benutze es, um Abfragen gegen mehrdimensionale Bäume zu machen, die als verschachtelte Mengen ausgedrückt werden.




Links