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

zobrazit poslední komentář, který má pouze 1 komentář na uživatele

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 BY doložka;
  • se používají s GROUP BY agregační funkce ;
  • jsou funkčně závislé na sloupcích, které se objevují v GROUP BY dolož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.



  1. Dynamický SQL - Kontrola syntaxe a sémantiky

  2. Pokyny krok za krokem pro instalaci Oracle Virtual Box

  3. Jak INTERSECT funguje na serveru SQL Server

  4. optimizer_search_depth v Google Cloud SQL