sql >> Databasteknik >  >> RDS >> Mysql

MYSQL visar felaktiga rader när du använder GROUP BY

Detta är ett klassiskt hinder som de flesta MySQL-programmerare stöter på.

  • Du har en kolumn ticket_id det är argumentet till GROUP BY . Distinkta värden i den här kolumnen definierar grupperna.
  • Du har en kolumn incoming_time det är argumentet till MAX() . Det största värdet i den här kolumnen över raderna i varje grupp returneras som värdet MAX() .
  • Du har alla andra kolumner i tabellartiklar. Värdena som returneras för dessa kolumner är godtyckliga, inte från samma rad där MAX() värde uppstår.

Databasen kan inte sluta sig till att du vill ha värden från samma rad där maxvärdet förekommer.

Tänk på följande fall:

  • Det finns flera rader där samma maxvärde förekommer. Vilken rad ska användas för att visa kolumnerna i article.* ?

  • Du skriver en fråga som returnerar både MIN() och MAX() . Detta är lagligt, men vilken rad ska article.* visa?

    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
    
  • Du använder en aggregerad funktion som AVG() eller SUM() , där ingen rad har det värdet. Hur kan databasen gissa vilken rad som ska visas?

    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
    

I de flesta märken av databas – såväl som själva SQL-standarden – är du inte tillåten att skriva en fråga som denna, på grund av oklarheten. Du kan inte inkludera någon kolumn i urvalslistan som inte finns i en aggregerad funktion eller namngiven i GROUP BY klausul.

MySQL är mer tillåtande. Det låter dig göra detta och överlåter till dig att skriva frågor utan tvetydighet. Om du har oklarheter väljer den värden från raden som är fysiskt först i gruppen (men detta är upp till lagringsmotorn).

För vad det är värt har SQLite också detta beteende, men det väljer det sista rad i gruppen för att lösa tvetydigheten. Gissa. Om SQL-standarden inte säger vad som ska göras är det upp till leverantörens implementering.

Här är en fråga som kan lösa ditt problem åt dig:

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;

Med andra ord, leta efter en rad (a1 ) för vilken det inte finns någon annan rad (a2 ) med samma ticket_id och en längre incoming_time . Om ingen längre incoming_time hittas, returnerar LEFT OUTER JOIN NULL istället för en matchning.



  1. Prestandavärde för COMB-guider

  2. hur man publicerar installationsprogrammet för c# fönster

  3. Vad är det bästa sättet att lagra koordinater (longitud/latitud, från Google Maps) i SQL Server?

  4. Slå samman två kolumner från två tabeller till en