Wstępny komentarz
Naucz się używać wyraźnej notacji JOIN, a nie starej (sprzed 1992 r.) niejawnej notacji dołączania.
Stary styl:
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
Preferowany styl:
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
Potrzebujesz warunku WŁĄCZENIA dla każdego DOŁĄCZENIA.
Ponadto personID
wartości w danych to ciągi, a nie liczby, więc musisz pisać
WHERE personTable.personid = "Ben"
na przykład, aby zapytanie zadziałało na pokazanych tabelach.
Główna odpowiedź
Poszukujesz agregatu agregatu:w tym przypadku maksimum liczebności. Tak więc każde ogólne rozwiązanie będzie obejmować zarówno MAX, jak i COUNT. Nie możesz zastosować MAX bezpośrednio do COUNT, ale możesz zastosować MAX do kolumny z podzapytania, w której kolumną jest COUNT.
Zbuduj zapytanie za pomocą Test-Driven Query Design — TDQD.
Wybierz ocenę osoby i transakcji
SELECT p.PersonID, t.Rating, t.TransactionID
FROM PersonTable AS p
JOIN TransactionTable AS t
ON p.TransactionID = t.TransactionID
Wybierz osobę, ocenę i liczbę wystąpień oceny
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
Ten wynik stanie się podzapytanie.
Sprawdź, ile razy dana osoba otrzymuje jakąkolwiek ocenę
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
Teraz wiemy, jaka jest maksymalna liczba dla każdej osoby.
Wymagany wynik
Aby uzyskać wynik, musimy wybrać wiersze z podzapytania, które mają maksymalną liczbę. Pamiętaj, że jeśli ktoś ma 2 dobre i 2 złe oceny (a 2 to maksymalna liczba ocen tego samego typu dla tej osoby), zostaną pokazane dwa rekordy dla tej osoby.
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
Jeśli chcesz również podać rzeczywistą liczbę ocen, możesz to łatwo wybrać.
To dość złożony fragment SQL. Nie chciałbym próbować pisać tego od zera. Rzeczywiście, prawdopodobnie nie zawracałbym sobie głowy; Rozwijałem to krok po kroku, mniej więcej tak, jak pokazano. Ale ponieważ debugowaliśmy podzapytania, zanim użyjemy ich w większych wyrażeniach, możemy być pewni odpowiedzi.
Z klauzulą
Należy zauważyć, że Standard SQL zawiera klauzulę WITH, która poprzedza instrukcję SELECT, nazywając podzapytanie. (Może być również używany do zapytań rekurencyjnych, ale nie potrzebujemy tego tutaj.)
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
To jest prostsze do napisania. Niestety, MySQL nie obsługuje jeszcze klauzuli WITH.
Powyższy kod SQL został przetestowany pod kątem oprogramowania IBM Informix Dynamic Server 11.70.FC2 działającego w systemie Mac OS X 10.7.4. Ten test ujawnił problem zdiagnozowany we wstępnym komentarzu. SQL dla głównej odpowiedzi działał poprawnie bez konieczności zmiany.