sql >> Database teknologi >  >> RDS >> Mysql

MYSQL - Sorter efter id i DESC rækkefølge, gruppe efter X

Du har misforstået, hvordan GROUP BY fungerer i SQL, på grund af en funktion i MySQL. I standard SQL SKAL hver ikke-aggregeret kolonne i SELECT-sætningen være i GROUP BY-sætningen (der er en undtagelse for kolonner, hvis værdier er 100 % afhængige af en kolonne, der allerede er i GROUP BY-sætningen, selvom få varianter af SQL understøtter denne undtagelse) .

MySQL håndhæver ikke dette som standard, men hvilke rækkeværdier der bruges til disse kolonner er ikke defineret. Selvom du måske får den, du gerne vil have, er du måske også ikke. Og selvom du gør det, er der en chance for, at det vil ændre sig i fremtiden.

Rækkefølgen er normalt uafhængig af GROUP BY, selvom hvis du ikke angiver en ORDER-klausul, vil resultaterne blive ordnet baseret på, hvad der var påkrævet for at udføre GROUP BY (dvs. hvis det hjælper at ordne rækkerne i én rækkefølge for at udføre GROUP BY så vil MySQL ikke gider at omarrangere posterne bagefter, medmindre du specifikt fortæller det med en ORDER BY-klausul).

Så med dine nuværende data, gruppering efter ads_post_id kunne værdien af ​​id, der returneres, være 22, 23, 24, 104, 250, 253 eller 767. Hvilken MySQL vælger at bruge, er ikke defineret.

Med din nuværende datafixing er dette trivielt, da du bare kan få MAX id:-

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

MAX returnerer 1 række for hver GROUP-værdi.

Det normale problem er, at folk vil have en anden kolonne til den række. Sig for eksempel, at hver af rækkerne i dine eksempeldata også havde en IP-adresse, og du ville have den, der svarede til det højeste id for 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 ---------------------------------------------------------------------------

I dette tilfælde kan du ikke bare bruge MAX. For eksempel hvis du prøvede:-

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

Du vil få følgende data returneret

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

Hvis du prøvede følgende i de fleste varianter af SQL, ville du få en fejl. I MySQL med standardindstillingerne ville du få et resultat, men hvilken IP-adresse der returneres er ikke defineret (og faktisk tilfældigt).

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

Løsningerne på dette er enten at få det maksimale id for hvert ads_post_id i en underforespørgsel og derefter at samle det tilbage til tabellen for at få resten af ​​værdierne:-

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
 

Et alternativ er at (ab)bruge aggregatfunktionen GROUP_CONCAT. GROUP_CONCAT vil bringe alle værdier sammenkædet tilbage i 1 felt, hver adskilt af et , (som standard). Du kan tilføje en ORDER BY-klausul for at tvinge den rækkefølge, de er sammenkædet i. Du kan bruge SUBSTRING_INDEX til at returnere alt til det første komma.

Dette kan være nyttigt for simple data, men bliver problematisk med tekstdata eller felter, der maksimalt er 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 
 


  1. Opret MySQL-funktion i Laravel 5.5

  2. Concat i If-erklæring

  3. Giver mysql CLI-værktøjet en måde at vise binære data på en konsolvenlig måde?

  4. Tilføj måneder til en dato i SQLite