Commentaire préliminaire
Veuillez apprendre à utiliser la notation JOIN explicite, et non l'ancienne notation de jointure implicite (avant 1992).
Style ancien :
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
Style préféré :
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
Vous avez besoin d'une condition ON pour chaque JOIN.
En outre, le personID
les valeurs dans les données sont des chaînes, pas des nombres, vous devez donc écrire
WHERE personTable.personid = "Ben"
par exemple, pour que la requête fonctionne sur les tables affichées.
Réponse principale
Vous cherchez à trouver un agrégat d'un agrégat :dans ce cas, le maximum d'un décompte. Ainsi, toute solution générale impliquera à la fois MAX et COUNT. Vous ne pouvez pas appliquer MAX directement à COUNT, mais vous pouvez appliquer MAX à une colonne à partir d'une sous-requête où la colonne se trouve être un COUNT.
Créez la requête à l'aide de Test-Driven Query Design (TDQD).
Sélectionnez la note de la personne et de la transaction
SELECT p.PersonID, t.Rating, t.TransactionID
FROM PersonTable AS p
JOIN TransactionTable AS t
ON p.TransactionID = t.TransactionID
Sélectionnez la personne, l'évaluation et le nombre d'occurrences d'évaluation
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
Ce résultat deviendra une sous-requête.
Trouvez le nombre maximum de fois où la personne obtient une note
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
Nous savons maintenant quel est le nombre maximum pour chaque personne.
Résultat requis
Pour obtenir le résultat, nous devons sélectionner les lignes de la sous-requête qui ont le nombre maximum. Notez que si quelqu'un a 2 bonnes et 2 mauvaises notes (et 2 est le nombre maximum de notes du même type pour cette personne), alors deux enregistrements seront affichés pour cette personne.
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
Si vous voulez que la note réelle compte aussi, c'est facile à sélectionner.
C'est un morceau de SQL assez complexe. Je détesterais essayer d'écrire cela à partir de zéro. En effet, je ne m'en soucierais probablement pas; Je le développerais étape par étape, plus ou moins comme indiqué. Mais comme nous avons débogué les sous-requêtes avant de les utiliser dans des expressions plus grandes, nous pouvons être sûrs de la réponse.
Clause AVEC
Notez que le SQL standard fournit une clause WITH qui préfixe une instruction SELECT, en nommant une sous-requête. (Il peut également être utilisé pour les requêtes récursives, mais nous n'en avons pas besoin ici.)
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
C'est plus simple à écrire. Malheureusement, MySQL ne prend pas encore en charge la clause WITH.
Le SQL ci-dessus a maintenant été testé sur IBM Informix Dynamic Server 11.70.FC2 exécuté sur Mac OS X 10.7.4. Ce test a révélé le problème diagnostiqué dans le commentaire préliminaire. Le SQL pour la réponse principale a fonctionné correctement sans avoir besoin d'être modifié.