Mysql
 sql >> база данни >  >> RDS >> Mysql

MYSQL показва неправилни редове при използване на GROUP BY

Това е класическо препятствие, с което повечето MySQL програмисти се сблъскват.

  • Имате колона ticket_id това е аргументът на GROUP BY . Отделни стойности в тази колона определят групите.
  • Имате колона incoming_time това е аргументът на MAX() . Най-голямата стойност в тази колона над редовете във всяка група се връща като стойността на MAX() .
  • Имате всички други колони от статия в таблицата. Върнатите стойности за тези колони са произволни, а не от същия ред, където MAX() се появява стойност.

Базата данни не може да заключи, че искате стойности от същия ред, където се появява максималната стойност.

Помислете за следните случаи:

  • Има няколко реда, където се появява една и съща максимална стойност. Кой ред трябва да се използва за показване на колоните на article.* ?

  • Пишете заявка, която връща и двата MIN() и MAX() . Това е законно, но кой ред трябва да article.* показване?

    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
    
  • Използвате агрегатна функция като AVG() или SUM() , където нито един ред няма тази стойност. Как базата данни да отгатне кой ред да покаже?

    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
    

В повечето марки бази данни -- както и в самия SQL стандарт -- вие не сте разрешени да напишете запитване като това, поради неяснотата. Не можете да включите колона в списъка за избор, която не е вътре в агрегатна функция или е наименувана в GROUP BY клауза.

MySQL е по-разрешителен. Позволява ви да правите това и оставя на вас да пишете заявки без двусмисленост. Ако имате неяснота, той избира стойности от реда, който физически е първи в групата (но това зависи от механизма за съхранение).

За какво си струва, SQLite също има това поведение, но избира последното ред в групата, за да разрешите неяснотата. Давай фигурирай. Ако SQL стандартът не казва какво да се прави, това зависи от реализацията на доставчика.

Ето една заявка, която може да реши проблема ви вместо вас:

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;

С други думи, потърсете ред (a1 ), за който няма друг ред (a2 ) със същия ticket_id и по-голямо incoming_time . Ако няма по-голямо incoming_time е намерен, LEFT OUTER JOIN връща NULL вместо съвпадение.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Искам да проверя дали записът съществува и ако не съществува, тогава искам да вмъкна този запис в базата данни с помощта на golang

  2. SQL:Синтактична грешка с intersect?

  3. MySQL и PDO:Може ли PDO::lastInsertId теоретично да се провали?

  4. PHP модел на свързване с единична база данни

  5. Не мога да използвам mysql_* функции след надграждане на PHP