Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MYSQL - Sortieren nach ID In DESC-Reihenfolge, Gruppieren nach X

Sie haben aufgrund einer Funktion von MySQL missverstanden, wie GROUP BY in SQL funktioniert. In Standard-SQL MUSS jede nicht aggregierte Spalte in der SELECT-Anweisung in der GROUP BY-Klausel enthalten sein (es gibt eine Ausnahme für Spalten, deren Werte zu 100 % von einer Spalte abhängen, die sich bereits in der GROUP BY-Klausel befindet, obwohl nur wenige SQL-Varianten diese Ausnahme unterstützen). .

MySQL erzwingt dies standardmäßig nicht, aber welche Zeilenwerte für diese Spalten verwendet werden, ist nicht definiert. Während Sie vielleicht das bekommen, was Sie wollen, können Sie es auch nicht. Und selbst wenn Sie dies tun, besteht die Möglichkeit, dass sich dies in Zukunft ändern wird.

Die Reihenfolge ist normalerweise unabhängig von GROUP BY, aber wenn Sie keine ORDER-Klausel angeben, werden die Ergebnisse basierend darauf geordnet, was für die Durchführung der GROUPing erforderlich war (d. h. wenn es hilfreich ist, die Zeilen in einer Reihenfolge zu ordnen, um dies zu tun GROUP BY, dann kümmert sich MySQL nicht darum, die Datensätze danach neu zu ordnen, es sei denn, Sie sagen es ausdrücklich mit einer ORDER BY-Klausel).

Mit Ihren aktuellen Daten, Gruppierung nach ads_post_id, könnte der zurückgegebene Wert von id also 22, 23, 24, 104, 250, 253 oder 767 sein. Welchen MySQL verwendet, ist nicht definiert.

Mit Ihrer aktuellen Datenkorrektur ist dies trivial, da Sie einfach die MAX-ID erhalten können:-

SELECT ads_post_id, MAX(id) 
FROM fb_ads 
GROUP BY ads_post_id 
LIMIT 6

MAX gibt 1 Zeile für jeden gruppierten Wert zurück.

Das normale Problem ist, dass die Leute eine andere Spalte für diese Zeile wollen. Angenommen, jede der Zeilen in Ihren Beispieldaten hatte auch eine IP-Adresse, und Sie wollten diejenige, die der höchsten ID für ads_post_id entspricht:-

id   | ads_post_id         ip_address
---------------------------------------------------------------------------
22   | 983314845117571     192.168.0.0
23   | 983314845117571     192.168.0.5
24   | 983314845117571     192.168.0.7    
104  | 983314845117571     192.168.0.0
250  | 983314845117571     192.168.0.4
253  | 983314845117571     192.168.0.6
767  | 983314845117571     192.168.0.1     
---------------------------------------------------------------------------

In diesem Fall können Sie nicht einfach MAX verwenden. Zum Beispiel, wenn Sie versucht haben:-

SELECT ads_post_id, MAX(id), MAX(ip_address) 
FROM fb_ads 
GROUP BY ads_post_id 
LIMIT 6

Sie würden die folgenden Daten zurückerhalten

id   | ads_post_id         ip_address
---------------------------------------------------------------------------
767  | 983314845117571     192.168.0.7     
---------------------------------------------------------------------------

Wenn Sie in den meisten SQL-Varianten Folgendes versuchen, erhalten Sie eine Fehlermeldung. In MySQL mit den Standardeinstellungen würden Sie ein Ergebnis erhalten, aber welche IP-Adresse zurückgegeben wird, ist nicht definiert (und tatsächlich zufällig).

SELECT ads_post_id, MAX(id), ip_address 
FROM fb_ads 
GROUP BY ads_post_id 
LIMIT 6

Die Lösungen dafür bestehen entweder darin, die maximale ID für jede ads_post_id in einer Unterabfrage zu erhalten und diese dann wieder mit der Tabelle zu verknüpfen, um die restlichen Werte zu erhalten:-

SELECT a.ads_post_id,
        a.id,
        a.ip_address
FROM fb_ads a
INNER JOIN
(
    SELECT ads_post_id, MAX(id) AS max_id 
    FROM fb_ads 
    GROUP BY ads_post_id 
) sub0
ON a.ads_post_id = sub0.ads_post_id
AND a.id = sub0.max_id

Eine Alternative ist die (ab)Verwendung der Aggregatfunktion GROUP_CONCAT. GROUP_CONCAT bringt alle verketteten Werte in 1 Feld zurück, jeweils getrennt durch ein , (standardmäßig). Sie können eine ORDER BY-Klausel hinzufügen, um die Reihenfolge zu erzwingen, in der sie verkettet werden. Dann können Sie SUBSTRING_INDEX verwenden, um alles bis zum ersten Komma zurückzugeben.

Dies kann für einfache Daten nützlich sein, wird aber problematisch bei Textdaten oder Feldern, die maximal NULL sind.

SELECT a.ads_post_id,
        SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY id DESC), ',', 1),
        SUBSTRING_INDEX(GROUP_CONCAT(ip_address ORDER BY id DESC), ',', 1)
FROM fb_ads 
GROUP BY ads_post_id