Hai frainteso come funziona GROUP BY in SQL, a causa di una funzionalità di MySQL. In SQL standard ogni colonna non aggregata nell'istruzione SELECT DEVE essere nella clausola GROUP BY (c'è un'eccezione per le colonne i cui valori dipendono al 100% da una colonna già nella clausola GROUP BY, sebbene poche versioni di SQL supportino questa esenzione) .
MySQL non lo applica per impostazione predefinita, ma i valori delle righe utilizzati per quelle colonne non sono definiti. Mentre potresti ottenere quello che desideri, potresti anche non farlo. E anche se lo fai, c'è la possibilità che cambi in futuro.
L'ordinamento è normalmente indipendente da GROUP BY, anche se se non si specifica una clausola ORDER i risultati verranno ordinati in base a ciò che è stato richiesto per eseguire il GROUPing (cioè, se aiuta a ordinare le righe in un ordine per eseguire GROUP BY quindi MySQL non si preoccuperà di riordinare i record in seguito a meno che tu non lo dica espressamente con una clausola ORDER BY).
Quindi con i tuoi dati attuali, raggruppando per ads_post_id il valore dell'id che viene restituito potrebbe essere 22, 23, 24, 104, 250, 253 o 767. Quale MySQL sceglie di utilizzare non è definito.
Con la tua attuale correzione dei dati, questo è banale in quanto puoi semplicemente ottenere l'ID MAX:-
SELECT ads_post_id, MAX(id)
FROM fb_ads
GROUP BY ads_post_id
LIMIT 6
MAX restituirà 1 riga per ogni valore GROUPed.
Il problema normale è che le persone vogliono un'altra colonna per quella riga. Ad esempio, supponiamo che ciascuna delle righe nei tuoi dati di esempio avesse anche un indirizzo IP e che volevi quello che equivaleva all'ID più alto per ads_post_id:-
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 questo caso non puoi semplicemente usare MAX. Ad esempio se hai provato:-
SELECT ads_post_id, MAX(id), MAX(ip_address)
FROM fb_ads
GROUP BY ads_post_id
LIMIT 6
Otterresti i seguenti dati restituiti
id | ads_post_id ip_address
---------------------------------------------------------------------------
767 | 983314845117571 192.168.0.7
---------------------------------------------------------------------------
Se hai provato quanto segue nella maggior parte delle versioni di SQL, otterresti un errore. In MySQL con le impostazioni predefinite otterresti un risultato, ma quale indirizzo IP viene restituito non è definito (e in effetti casuale).
SELECT ads_post_id, MAX(id), ip_address
FROM fb_ads
GROUP BY ads_post_id
LIMIT 6
Le soluzioni a questo sono ottenere l'id massimo per ogni ads_post_id in una sottoquery e quindi unirlo alla tabella per ottenere il resto dei valori:-
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
Un'alternativa è (ab)utilizzare la funzione di aggregazione GROUP_CONCAT. GROUP_CONCAT riporterà tutti i valori concatenati insieme in 1 campo, ciascuno separato da un , (per impostazione predefinita). Puoi aggiungere una clausola ORDER BY per forzare l'ordine in cui sono concatenati. Puoi usare SUBSTRING_INDEX per restituire tutto fino alla prima virgola.
Questo può essere utile per dati semplici, ma diventa problematico con dati di testo o campi che possono essere al massimo NULL.
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