sql >> Database >  >> RDS >> Mysql

MYSQL toont onjuiste rijen bij gebruik van GROUP BY

Dit is een klassieke hindernis waar de meeste MySQL-programmeurs tegenaan lopen.

  • Je hebt een kolom ticket_id dat is het argument voor GROUP BY . Verschillende waarden in deze kolom definiëren de groepen.
  • Je hebt een kolom incoming_time dat is het argument voor MAX() . De grootste waarde in deze kolom over de rijen in elke groep wordt geretourneerd als de waarde van MAX() .
  • Je hebt alle andere kolommen met tabelartikel. De geretourneerde waarden voor deze kolommen zijn willekeurig, niet van dezelfde rij waar de MAX() waarde komt voor.

De database kan niet afleiden dat u waarden wilt uit dezelfde rij waar de maximale waarde voorkomt.

Denk aan de volgende gevallen:

  • Er zijn meerdere rijen waar dezelfde maximale waarde voorkomt. Welke rij moet worden gebruikt om de kolommen van article.* . weer te geven ?

  • U schrijft een query die zowel de MIN() en de MAX() . Dit is legaal, maar welke rij moet article.* laten zien?

    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
    
  • U gebruikt een verzamelfunctie zoals AVG() of SUM() , waarbij geen enkele rij die waarde heeft. Hoe moet de database raden welke rij moet worden weergegeven?

    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
    

In de meeste databasemerken -- evenals de SQL-standaard zelf -- is het niet toegestaan om een ​​query als deze te schrijven, vanwege de dubbelzinnigheid. U kunt geen kolommen in de selectielijst opnemen die niet in een statistische functie staan ​​of die niet in de GROUP BY staan. clausule.

MySQL is toleranter. Het laat u dit doen en laat het aan u over om vragen te schrijven zonder dubbelzinnigheid. Als je dubbelzinnigheid hebt, selecteert het waarden uit de rij die fysiek als eerste in de groep staat (maar dit is aan de opslagengine).

Voor wat het waard is, SQLite heeft ook dit gedrag, maar het kiest de laatste rij in de groep om de dubbelzinnigheid op te lossen. Ga figuur. Als de SQL-standaard niet zegt wat te doen, ligt het aan de implementatie van de leverancier.

Hier is een vraag die uw probleem voor u kan oplossen:

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;

Met andere woorden, zoek naar een rij (a1 ) waarvoor er geen andere rij is (a2 ) met dezelfde ticket_id en een grotere incoming_time . Indien geen grotere incoming_time wordt gevonden, retourneert de LEFT OUTER JOIN NULL in plaats van een overeenkomst.



  1. Gebruik van Python3 mysqlclient-1.3.6 (ook bekend als PyMySQL)?

  2. Automatische verwijdering van vastgelopen processen in MS SQL Server

  3. Waar zijn de PostgreSQL-logboeken op macOS?

  4. Hoe output onderdrukken en controleren of een commando succesvol is?