sql >> Databáze >  >> RDS >> Mysql

MYSQL - Řazení podle ID v pořadí DESC, skupina podle X

Špatně jste pochopili, jak GROUP BY funguje v SQL, kvůli funkci MySQL. Ve standardním SQL MUSÍ být každý neagregovaný sloupec v příkazu SELECT v klauzuli GROUP BY (existuje výjimka pro sloupce, jejichž hodnoty jsou 100% závislé na sloupci již v klauzuli GROUP BY, ačkoli tuto výjimku podporuje jen několik variant SQL) .

MySQL toto standardně nevynucuje, ale není definováno, které hodnoty řádků jsou pro tyto sloupce použity. I když můžete získat ten, který chcete, také nemusíte. A i když to uděláte, existuje šance, že se to v budoucnu změní.

Řazení je normálně nezávislé na GROUP BY, i když pokud neurčíte klauzuli ORDER, budou výsledky seřazeny podle toho, co bylo požadováno k provedení GROUPing (tj. pokud pomůže seřadit řádky v jednom pořadí, GROUP BY se pak MySQL nebude obtěžovat s přeuspořádáním záznamů poté, pokud mu to výslovně neřeknete pomocí klauzule ORDER BY).

Takže s vašimi aktuálními daty může být seskupení podle ads_post_id vrácená hodnota id 22, 23, 24, 104, 250, 253 nebo 767. Není definováno, který z nich se MySQL rozhodne použít.

S vaší aktuální opravou dat je to triviální, protože můžete získat pouze MAX id:-

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

MAX vrátí 1 řádek pro každou seskupenou hodnotu.

Normální problém je, že lidé chtějí pro tento řádek další sloupec. Řekněme například, že každý z řádků ve vašich ukázkových datech měl také IP adresu a chtěli jste tu, která se rovnala nejvyššímu id pro 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     
---------------------------------------------------------------------------

V tomto případě nemůžete použít pouze MAX. Pokud jste například zkusili:-

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

Vrátili byste následující data

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

Pokud byste vyzkoušeli následující ve většině variant SQL, dostanete chybu. V MySQL s výchozím nastavením byste dostali výsledek, ale vrácená IP adresa není definována (a ve skutečnosti náhodná).

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

Řešením je buď získat maximální id pro každý ads_post_id v dílčím dotazu a poté jej připojit zpět k tabulce, abyste získali zbytek hodnot:-

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

Alternativou je (ab)použití agregační funkce GROUP_CONCAT. GROUP_CONCAT vrátí všechny hodnoty spojené dohromady do 1 pole, každé oddělené , (ve výchozím nastavení). Můžete přidat klauzuli ORDER BY a vynutit tak pořadí, do kterého jsou zřetězeni. Pomocí SUBSTRING_INDEX můžete vrátit vše až po první čárku.

To může být užitečné pro jednoduchá data, ale stává se to problematické u textových dat nebo polí, která mají max. hodnotu 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. Jak Oracle SELECT FROM dual pracuje s více poli

  2. Nelze vytvořit rozšíření plv8 postgresql

  3. Jak získat velikost databáze mysql?

  4. convert_tz vrátí hodnotu null