Proč to nefunguje s GROUP BY
SELECT * nelze použít s GROUP BY; je to neplatný SQL. GROUP BY nevybírá řádky tabulky. Vytvoří skupiny řádků pomocí poskytnutých výrazů a poté z každé skupiny vygeneruje nový záznam a vypočítá každý sloupec tohoto nového záznamu pomocí hodnot zahrnutých ve výrazu.
Sloupce, které se objeví v SELECT klauzule musí splňovat jedno z následujících pravidel:
- objeví se také v
GROUP BYdoložka; - se používají s
GROUP BYagregační funkce ; - jsou funkčně závislé na sloupcích, které se objevují v
GROUP BYdoložka.
Zatímco * je zkratka pro všechny názvy sloupců tabulek použitých v dotazu, pro váš dotaz pouze user splňují jeden z výše uvedených požadavků.
Před verzí 5.7.5
MySQL neimplementovalo třetí pravidlo výše. Používá se k přijímání dotazů, které obsahují SELECT klauzule, které nenásledují žádný z GROUP BY požadavky. Hodnota vrácená dotazem pro takové sloupce byla neurčitá
.
Od verze 5.7.5 MySQL odmítá GROUP BY dotazy, které splňují požadavky.
Řešení
Ať tak či onak, řešení vašeho problému nezahrnuje GROUP BY . To lze snadno provést pomocí LEFT JOIN se správnými podmínkami:
SELECT lc.*
FROM comments lc # 'lc' from 'last comment'
LEFT JOIN comments nc # 'nc' from 'newer comment'
ON lc.user = nc.user # both comments belong to the same user
AND lc.id < nc.id # 'nc' is newer than 'lc'
WHERE nc.id IS NULL # there is no 'newer comment'
ORDER BY lc.id DESC
LIMIT 10
Jak to funguje
Spojí tabulku comments , s aliasem lc ("lc" z "posledního komentáře" uživatele) proti sobě, s aliasem nc ("nc" z "novějšího komentáře"). Klauzule spojení odpovídá každému záznamu lc se všemi položkami nc které patří stejnému uživateli (lc.user = nc.user ) a jsou novější (lc.id < nc.id; Předpokládal jsem, že ID jsou přidělována postupně a novější komentáře mají větší hodnoty pro id ).
Použití LEFT JOIN zajišťuje, že každý řádek lc se objeví ve výsledku spojení, i když v nc nebyl nalezen žádný odpovídající řádek (protože neexistuje žádný novější komentář stejného uživatele). V tomto případě NULL se používá místo polí nc . WHERE klauzule zachovává v konečné sadě výsledků pouze řádky, které mají NULL v nc.id; to znamená v lc obsahují nejnovější komentář každého uživatele.
SELECT klauzule obsahuje všechna pole lc (ty z nc všechny jsou NULL , tak jako tak). ORDER BY klauzuli lze použít k seřazení sady výsledků. ORDER BY lc.id DESC na první místo umístí nejnovější komentáře a LIMIT klauzule udržuje výslednou sadu na slušné velikosti.