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

MYSQL zobrazuje nesprávné řádky při použití GROUP BY

Toto je klasická překážka, na kterou naráží většina programátorů MySQL.

  • Máte sloupec ticket_id to je argument pro GROUP BY . Odlišné hodnoty v tomto sloupci definují skupiny.
  • Máte sloupec incoming_time to je argument pro MAX() . Největší hodnota v tomto sloupci přes řádky v každé skupině je vrácena jako hodnota MAX() .
  • Máte všechny ostatní sloupce článku tabulky. Hodnoty vrácené pro tyto sloupce jsou libovolné, nikoli ze stejného řádku, kde je MAX() dojde k hodnotě.

Databáze nemůže odvodit, že chcete hodnoty ze stejného řádku, kde se vyskytuje maximální hodnota.

Přemýšlejte o následujících případech:

  • Existuje více řádků, kde se vyskytuje stejná maximální hodnota. Který řádek by měl být použit k zobrazení sloupců article.* ?

  • Napíšete dotaz, který vrátí obě MIN() a MAX() . To je legální, ale který řádek by měl article.* show?

    SELECT article.* , MIN(article.incoming_time), MAX(article.incoming_time)
    FROM ticket, article
    WHERE ticket.id = article.ticket_id
    AND ticket.queue_id = 1
    GROUP BY article.ticket_id
    
  • Používáte agregační funkci, jako je AVG() nebo SUM() , kde tuto hodnotu nemá žádný řádek. Jak má databáze odhadnout, který řádek má zobrazit?

    SELECT article.* , AVG(article.incoming_time)
    FROM ticket, article
    WHERE ticket.id = article.ticket_id
    AND ticket.queue_id = 1
    GROUP BY article.ticket_id
    

Ve většině značek databází – stejně jako v samotném standardu SQL – nejste povoleni napsat dotaz, jako je tento, kvůli nejednoznačnosti. Do výběrového seznamu nemůžete zahrnout žádný sloupec, který není v agregační funkci nebo není pojmenován v GROUP BY doložka.

MySQL je tolerantnější. Umožňuje vám to a nechává na vás, abyste dotazy napsali bez dvojznačnosti. Pokud máte nejasnosti, vybere hodnoty z řádku, který je fyzicky první ve skupině (ale to záleží na úložišti).

Za co to stojí, SQLite má také toto chování, ale volí poslední řádek ve skupině, aby se vyřešila nejednoznačnost. Jdi zjistit. Pokud standard SQL neříká, co dělat, je to na implementaci dodavatele.

Zde je dotaz, který vám může vyřešit váš problém:

SELECT a1.* , a1.incoming_time AS maxtime
FROM ticket t JOIN article a1 ON (t.id = a1.ticket_id)
LEFT OUTER JOIN article a2 ON (t.id = a2.ticket_id 
  AND a1.incoming_time < a2.incoming_time)
WHERE t.queue_id = 1
  AND a2.ticket_id IS NULL;

Jinými slovy, vyhledejte řádek (a1 ), pro který neexistuje žádný další řádek (a2 ) se stejným ticket_id a větší incoming_time . Pokud není větší incoming_time je nalezen, LEFT OUTER JOIN vrátí NULL místo shody.



  1. Oracle JDBC ojdbc6 Jar jako Maven Dependency

  2. Jak zřetězit všechny sloupce ve výběru pomocí SQL Server

  3. Záznam vrácený z funkce má zřetězené sloupce

  4. PostgreSQL ODLIŠUJE S různou ORDER BY