Preliminär kommentar
Lär dig att använda den explicita JOIN-notationen, inte den gamla (före 1992) implicita join-notationen.
Gammal stil:
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
Önskad stil:
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
Du behöver ett PÅ-villkor för varje JOIN.
Även personID
värden i datan är strängar, inte siffror, så du måste skriva
WHERE personTable.personid = "Ben"
till exempel för att få frågan att fungera på tabellerna som visas.
Huvudsvar
Du försöker hitta ett aggregat av ett aggregat:i det här fallet är det maximala antalet. Så, alla generella lösningar kommer att involvera både MAX och COUNT. Du kan inte tillämpa MAX direkt på COUNT, men du kan tillämpa MAX på en kolumn från en underfråga där kolumnen råkar vara ett COUNT.
Bygg upp frågan med testdriven frågedesign — TDQD.
Välj person och transaktionsbetyg
SELECT p.PersonID, t.Rating, t.TransactionID
FROM PersonTable AS p
JOIN TransactionTable AS t
ON p.TransactionID = t.TransactionID
Välj person, betyg och antal förekomster av betyg
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
Detta resultat kommer att bli en underfråga.
Hitta det maximala antalet gånger personen får något betyg
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
Nu vet vi vilket som är det maximala antalet för varje person.
Obligatoriskt resultat
För att få resultatet måste vi välja de rader från underfrågan som har det maximala antalet. Observera att om någon har 2 bra och 2 dåliga betyg (och 2 är det maximala antalet betyg av samma typ för den personen), kommer två poster att visas för den personen.
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
Om du vill ha det faktiska antalet betyg också, är det enkelt att välja.
Det är en ganska komplex del av SQL. Jag skulle hata att försöka skriva det från början. Ja, jag skulle nog inte bry mig; Jag skulle utveckla det steg-för-steg, mer eller mindre som visas. Men eftersom vi har felsökt underfrågorna innan vi använder dem i större uttryck, kan vi vara säkra på svaret.
WITH klausul
Observera att Standard SQL tillhandahåller en WITH-sats som prefix till en SELECT-sats och namnger en underfråga. (Det kan också användas för rekursiva frågor, men vi behöver det inte här.)
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
Det här är enklare att skriva. Tyvärr stöder MySQL ännu inte WITH-satsen.
SQL ovan har nu testats mot IBM Informix Dynamic Server 11.70.FC2 som körs på Mac OS X 10.7.4. Det testet avslöjade problemet som diagnostiserades i den preliminära kommentaren. SQL för huvudsvaret fungerade korrekt utan att behöva ändras.