sql >> Databasteknik >  >> RDS >> Mysql

MYSQL - Ordna efter ID I DESC Ordning, Gruppera efter X

Du har missförstått hur GROUP BY fungerar i SQL, på grund av en funktion i MySQL. I standard SQL MÅSTE varje icke aggregerad kolumn i SELECT-satsen finnas i GROUP BY-satsen (det finns ett undantag för kolumner vars värden är 100 % beroende av en kolumn som redan finns i GROUP BY-satsen, även om få varianter av SQL stöder detta undantag) .

MySQL upprätthåller inte detta som standard, men vilka radvärden som används för dessa kolumner är inte definierade. Även om du kanske får den du vill ha, kanske du inte heller. Och även om du gör det finns det en chans att det kommer att förändras i framtiden.

Beställningen är normalt oberoende av GROUP BY, även om du inte anger en ORDER-klausul kommer resultaten att ordnas baserat på vad som krävdes för att utföra GROUP BY (dvs. om det hjälper att ordna raderna i en ordning för att göra GROUP BY då kommer MySQL inte bry sig om att ordna om posterna efteråt om du inte specifikt säger till det med en ORDER BY-klausul).

Så med din nuvarande data, gruppering efter ads_post_id kan värdet på id som returneras vara 22, 23, 24, 104, 250, 253 eller 767. Vilken MySQL väljer att använda är inte definierad.

Med din nuvarande datafixning är detta trivialt eftersom du bara kan få MAX id:-

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

MAX returnerar 1 rad för varje GROUPerat värde.

Det normala problemet är att folk vill ha en annan kolumn för den raden. Säg till exempel att var och en av raderna i din exempeldata också hade en IP-adress, och du ville ha den som motsvarar det högsta ID:t för 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 det här fallet kan du inte bara använda MAX. Till exempel om du försökte:-

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

Du skulle få följande data returnerade

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

Om du provade följande i de flesta varianter av SQL skulle du få ett felmeddelande. I MySQL med standardinställningarna skulle du få ett resultat, men vilken IP-adress som returneras är inte definierat (och i själva verket slumpmässigt).

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

Lösningarna på detta är antingen att få max-id för varje ads_post_id i en underfråga och sedan koppla tillbaka det till tabellen för att få resten av värdena:-

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

Ett alternativ är att (ab)använda aggregatfunktionen GROUP_CONCAT. GROUP_CONCAT kommer att ta tillbaka alla värden som är sammanlänkade i ett fält, vart och ett separerat av en , (som standard). Du kan lägga till en ORDER BY-sats för att tvinga fram den ordning de är sammanlänkade till. Du kan använda SUBSTRING_INDEX för att returnera allt till första kommatecken.

Detta kan vara användbart för enkla data, men blir problematiskt med textdata eller fält som max är 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. Spridning av Oracle-transaktioner mellan C++ och Java

  2. SQL-fråga för att summera data

  3. PG::Fel - numeriskt fältspill på Heroku

  4. Installera Percona/MySQL obevakad på Ubuntu