Ihre Lösung verwendet eine Erweiterung der GROUP BY- Klausel, mit der Sie nach bestimmten Feldern gruppieren können (in diesem Fall nur post_author
):
GROUP BY wp_posts.post_author
und wählen Sie nicht aggregierte Spalten aus:
SELECT wp_posts.*
die nicht in der group by-Klausel aufgeführt sind oder die nicht in einer Aggregatfunktion (MIN, MAX, COUNT usw.) verwendet werden.
Richtige Verwendung der Erweiterung der GROUP BY-Klausel
Dies ist nützlich, wenn alle Werte nicht aggregierter Spalten für jede Zeile gleich sind.
Angenommen, Sie haben einen Tisch GardensFlowers
( name
des Gartens, der im Garten flower
wächst):
INSERT INTO GardensFlowers VALUES
('Central Park', 'Magnolia'),
('Hyde Park', 'Tulip'),
('Gardens By The Bay', 'Peony'),
('Gardens By The Bay', 'Cherry Blossom');
und Sie möchten alle Blumen extrahieren, die in einem Garten wachsen, in dem mehrere Blumen wachsen. Dann müssen Sie eine Unterabfrage verwenden, zum Beispiel könnten Sie diese verwenden:
SELECT GardensFlowers.*
FROM GardensFlowers
WHERE name IN (SELECT name
FROM GardensFlowers
GROUP BY name
HAVING COUNT(DISTINCT flower)>1);
Wenn Sie stattdessen alle Blumen extrahieren müssen, die die einzigen Blumen im Garder sind, können Sie einfach die HAVING-Bedingung in ändern HAVING COUNT(DISTINCT flower)=1
, aber MySql ermöglicht Ihnen auch Folgendes:
SELECT GardensFlowers.*
FROM GardensFlowers
GROUP BY name
HAVING COUNT(DISTINCT flower)=1;
Keine Unterabfrage, kein Standard-SQL, aber einfacher.
Falsche Verwendung der Erweiterung der GROUP BY-Klausel
Aber was passiert, wenn Sie nicht aggregierte Spalten auswählen, die nicht für jede Zeile gleich sind? Welchen Wert wählt MySql für diese Spalte?
Es sieht so aus, als würde MySQL immer den ERSTEN Wert auswählen, auf den es stößt.
Um sicherzustellen, dass der erste Wert, auf den er trifft, genau der gewünschte Wert ist, müssen Sie a GROUP BY
auf eine geordnete Abfrage anwenden , daher muss eine Unterabfrage verwendet werden. Sie können es nicht anders machen.
Unter der Annahme, dass MySql immer die erste Zeile auswählt, auf die es trifft, sortieren Sie die Zeilen vor der GROUP BY korrekt. Wenn Sie die Dokumentation jedoch sorgfältig lesen, werden Sie leider feststellen, dass diese Annahme nicht zutrifft.
Bei der Auswahl nicht aggregierter Spalten, die nicht immer gleich sind, kann MySql einen beliebigen Wert auswählen, sodass der resultierende Wert, der tatsächlich angezeigt wird, unbestimmt ist .
Ich sehe, dass dieser Trick, um den ersten Wert einer nicht aggregierten Spalte zu erhalten, häufig verwendet wird und normalerweise / fast immer funktioniert. Ich verwende ihn manchmal auch (auf eigenes Risiko). Da dies jedoch nicht dokumentiert ist, können Sie sich nicht auf dieses Verhalten verlassen.
Dieser Link (danke ypercube!) Der GROUP BY-Trick wurde weg optimiert. Er zeigt eine Situation, in der dieselbe Abfrage unterschiedliche Ergebnisse zwischen MySql und MariaDB zurückgibt, wahrscheinlich aufgrund einer anderen Optimierungs-Engine.
Wenn dieser Trick funktioniert, ist es nur eine Frage des Glücks.
Die akzeptierte Antwort auf die andere Frage erscheint mir falsch:
HAVING wp_posts.post_date = MAX(wp_posts.post_date)
wp_posts.post_date
ist eine nicht aggregierte Spalte, und ihr Wert wird offiziell unbestimmt sein, aber es wird wahrscheinlich die erste sein, die post_date
angetroffen wird. Da der GROUP BY-Trick jedoch auf eine ungeordnete Tabelle angewendet wird, ist nicht sicher, welche zuerst post_date
angetroffen wird.
Es werden wahrscheinlich Beiträge zurückgegeben, die die einzigen Beiträge eines einzelnen Autors sind, aber selbst dies ist nicht immer sicher.
Eine mögliche Lösung
Ich denke, dass dies eine mögliche Lösung sein könnte:
SELECT wp_posts.*
FROM wp_posts
WHERE id IN (
SELECT max(id)
FROM wp_posts
WHERE (post_author, post_date) = (
SELECT post_author, max(post_date)
FROM wp_posts
WHERE wp_posts.post_status='publish'
AND wp_posts.post_type='post'
GROUP BY post_author
) AND wp_posts.post_status='publish'
AND wp_posts.post_type='post'
GROUP BY post_author
)
Bei der inneren Abfrage gebe ich das maximale Post-Datum für jeden Autor zurück. Ich berücksichtige dann die Tatsache, dass derselbe Autor theoretisch zwei Beiträge gleichzeitig haben könnte, sodass ich nur die maximale ID erhalte. Und dann gebe ich alle Zeilen zurück, die diese maximalen IDs haben. Es könnte schneller mit Joins anstelle der IN-Klausel gemacht werden.
(Wenn Sie sicher sind, dass dies ID
nur zunimmt und dies ID1 > ID2
auch bedeutet, post_date1 > post_date2
könnte die Abfrage viel einfacher gestaltet werden, aber ich bin mir nicht sicher, ob dies der Fall ist.)
post_author
undpost_date
sind nicht genug, um eine eindeutige Zeile zu erhalten, daher muss es mehr geben, um eine eindeutige Zeile propost_author