Commento preliminare
Impara a usare la notazione esplicita JOIN, non la vecchia notazione di join implicita (precedente al 1992).
Vecchio stile:
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
Stile preferito:
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
Hai bisogno di una condizione ON per ogni JOIN.
Inoltre, il personID
i valori nei dati sono stringhe, non numeri, quindi dovresti scrivere
WHERE personTable.personid = "Ben"
ad esempio, per far funzionare la query sulle tabelle mostrate.
Risposta principale
Stai cercando di trovare un aggregato di un aggregato:in questo caso, il massimo di un conteggio. Quindi, qualsiasi soluzione generale coinvolgerà sia MAX che COUNT. Non puoi applicare MAX direttamente a COUNT, ma puoi applicare MAX a una colonna da una sottoquery in cui la colonna è COUNT.
Crea la query utilizzando Test-Driven Query Design — TDQD.
Seleziona persona e valutazione transazione
SELECT p.PersonID, t.Rating, t.TransactionID
FROM PersonTable AS p
JOIN TransactionTable AS t
ON p.TransactionID = t.TransactionID
Seleziona persona, valutazione e numero di occorrenze di valutazione
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
Questo risultato diventerà una sottoquery.
Trova il numero massimo di volte in cui la persona ottiene una valutazione
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
Ora sappiamo qual è il conteggio massimo per ogni persona.
Risultato richiesto
Per ottenere il risultato, dobbiamo selezionare le righe della sottoquery che hanno il conteggio massimo. Tieni presente che se qualcuno ha 2 valutazioni buone e 2 cattive (e 2 è il numero massimo di valutazioni dello stesso tipo per quella persona), verranno mostrati due record per quella persona.
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
Se desideri anche il conteggio effettivo delle valutazioni, puoi selezionarlo facilmente.
Questo è un pezzo di SQL abbastanza complesso. Mi dispiacerebbe provare a scriverlo da zero. In effetti, probabilmente non mi preoccuperei; Lo svilupperei passo dopo passo, più o meno come mostrato. Ma poiché abbiamo eseguito il debug delle sottoquery prima di usarle in espressioni più grandi, possiamo essere certi della risposta.
CON clausola
Si noti che Standard SQL fornisce una clausola WITH che antepone un'istruzione SELECT, denominando una sottoquery. (Può anche essere usato per query ricorsive, ma non ne abbiamo bisogno qui.)
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
Questo è più semplice da scrivere. Sfortunatamente, MySQL non supporta ancora la clausola WITH.
L'SQL sopra è stato ora testato rispetto a IBM Informix Dynamic Server 11.70.FC2 in esecuzione su Mac OS X 10.7.4. Quel test ha esposto il problema diagnosticato nel commento preliminare. L'SQL per la risposta principale ha funzionato correttamente senza bisogno di essere modificato.