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

SQL:Връщане на най-често срещаната стойност за всеки човек

Предварителен коментар

Моля, научете се да използвате изричната нотация JOIN, а не старата (преди 1992 г.) неявна нотация за присъединяване.

Стар стил:

SELECT transactionTable.rating as MostCommonRating 
FROM personTable, transactionTable 
WHERE personTable.transactionid = transactionTable.transactionid 
AND personTable.personid = 1
GROUP BY transactionTable.rating 
ORDER BY COUNT(transactionTable.rating) desc 
LIMIT 1

Предпочитан стил:

SELECT transactionTable.rating AS MostCommonRating 
  FROM personTable
  JOIN transactionTable 
    ON personTable.transactionid = transactionTable.transactionid 
 WHERE personTable.personid = 1
 GROUP BY transactionTable.rating 
 ORDER BY COUNT(transactionTable.rating) desc 
 LIMIT 1

Имате нужда от условие ON за всяко JOIN.

Също така, personID стойностите в данните са низове, а не числа, така че ще трябва да напишете

 WHERE personTable.personid = "Ben"

например, за да накарате заявката да работи върху показаните таблици.

Основен отговор

Вие се стремите да намерите съвкупност от агрегат:в този случай, максимумът от брой. Така че всяко общо решение ще включва както MAX, така и COUNT. Не можете да приложите MAX директно към COUNT, но можете да приложите MAX към колона от подзаявка, където колоната е COUNT.

Изградете заявката с помощта на Test-Driven Query Design — TDQD.

Изберете лице и оценка на транзакцията

SELECT p.PersonID, t.Rating, t.TransactionID
  FROM PersonTable AS p
  JOIN TransactionTable AS t
    ON p.TransactionID = t.TransactionID

Изберете човек, рейтинг и брой случаи на оценка

SELECT p.PersonID, t.Rating, COUNT(*) AS RatingCount
  FROM PersonTable AS p
  JOIN TransactionTable AS t
    ON p.TransactionID = t.TransactionID
 GROUP BY p.PersonID, t.Rating

Този резултат ще се превърне в подзаявка.

Намерете максималния брой пъти, в които лицето получава някаква оценка

SELECT s.PersonID, MAX(s.RatingCount)
  FROM (SELECT p.PersonID, t.Rating, COUNT(*) AS RatingCount
          FROM PersonTable AS p
          JOIN TransactionTable AS t
            ON p.TransactionID = t.TransactionID
         GROUP BY p.PersonID, t.Rating
       ) AS s
 GROUP BY s.PersonID

Сега знаем кой е максималният брой за всеки човек.

Задължителен резултат

За да получим резултата, трябва да изберем редовете от подзаявката, които имат максимален брой. Имайте предвид, че ако някой има 2 добри и 2 лоши оценки (и 2 е максималният брой оценки от същия тип за това лице), тогава за това лице ще се покажат два записа.

SELECT s.PersonID, s.Rating
  FROM (SELECT p.PersonID, t.Rating, COUNT(*) AS RatingCount
          FROM PersonTable AS p
          JOIN TransactionTable AS t
            ON p.TransactionID = t.TransactionID
         GROUP BY p.PersonID, t.Rating
       ) AS s
  JOIN (SELECT s.PersonID, MAX(s.RatingCount) AS MaxRatingCount
          FROM (SELECT p.PersonID, t.Rating, COUNT(*) AS RatingCount
                  FROM PersonTable AS p
                  JOIN TransactionTable AS t
                    ON p.TransactionID = t.TransactionID
                 GROUP BY p.PersonID, t.Rating
               ) AS s
         GROUP BY s.PersonID
       ) AS m
    ON s.PersonID = m.PersonID AND s.RatingCount = m.MaxRatingCount

Ако искате и действителния брой оценки, това се избира лесно.

Това е доста сложна част от SQL. Не бих искал да опитам да го напиша от нулата. Наистина, вероятно не бих се притеснявал; Бих го разработил стъпка по стъпка, повече или по-малко, както е показано. Но тъй като сме отстранили грешките в подзаявките, преди да ги използваме в по-големи изрази, можем да бъдем уверени в отговора.

клауза WITH

Обърнете внимание, че стандартният SQL предоставя клауза WITH, която поставя префикс на израз SELECT, назовавайки подзаявка. (Може да се използва и за рекурсивни заявки, но тук нямаме нужда от това.)

WITH RatingList AS
     (SELECT p.PersonID, t.Rating, COUNT(*) AS RatingCount
        FROM PersonTable AS p
        JOIN TransactionTable AS t
          ON p.TransactionID = t.TransactionID
       GROUP BY p.PersonID, t.Rating
     )
SELECT s.PersonID, s.Rating
  FROM RatingList AS s
  JOIN (SELECT s.PersonID, MAX(s.RatingCount) AS MaxRatingCount
          FROM RatingList AS s
         GROUP BY s.PersonID
       ) AS m
    ON s.PersonID = m.PersonID AND s.RatingCount = m.MaxRatingCount

Това е по-лесно за писане. За съжаление MySQL все още не поддържа клаузата WITH.

SQL по-горе вече е тестван срещу IBM Informix Dynamic Server 11.70.FC2, работещ на Mac OS X 10.7.4. Този тест разкри проблема, диагностициран в предварителния коментар. SQL за основния отговор работи правилно, без да е необходимо да се променя.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. mysqldump чрез SSH към локален компютър

  2. Подготвен изявление за MySQL - Как да преминете през

  3. MySQL автоматичен низ към цяло число в клауза where?

  4. Множество, но взаимно изключващи се външни ключове - това ли е пътят?

  5. MySQL изхвърля в CSV текстови файлове с имена на колони в горната част?