Předběžný komentář
Naučte se prosím používat explicitní zápis JOIN, nikoli starý (před rokem 1992) implicitní zápis spojení.
Starý 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
Preferovaný 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
Pro každý JOIN potřebujete podmínku ON.
Také personID
hodnoty v datech jsou řetězce, nikoli čísla, takže budete muset napsat
WHERE personTable.personid = "Ben"
například, aby dotaz fungoval na zobrazených tabulkách.
Hlavní odpověď
Snažíte se najít souhrn souhrnu:v tomto případě maximum počtu. Jakékoli obecné řešení tedy bude zahrnovat MAX i COUNT. MAX nelze použít přímo na COUNT, ale můžete použít MAX na sloupec z dílčího dotazu, kde je sloupec náhodou COUNT.
Sestavte dotaz pomocí Test-Driven Query Design — TDQD.
Vyberte osobu a hodnocení transakce
SELECT p.PersonID, t.Rating, t.TransactionID
FROM PersonTable AS p
JOIN TransactionTable AS t
ON p.TransactionID = t.TransactionID
Vyberte osobu, hodnocení a počet výskytů hodnocení
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
Tento výsledek se stane dílčím dotazem.
Najděte maximální počet, kolikrát daná osoba získala jakékoli hodnocení
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
Nyní víme, jaký je maximální počet pro každou osobu.
Požadovaný výsledek
Abychom získali výsledek, musíme z dílčího dotazu vybrat řádky, které mají maximální počet. Všimněte si, že pokud má někdo 2 dobrá a 2 špatná hodnocení (a 2 je maximální počet hodnocení stejného typu pro tuto osobu), zobrazí se pro tuto osobu dva záznamy.
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
Pokud chcete také skutečný počet hodnocení, můžete to snadno vybrat.
To je poměrně složitá část SQL. Nerad bych to zkusil napsat od začátku. Pravděpodobně bych se tím neobtěžoval; Vyvíjel bych to krok za krokem, víceméně tak, jak je ukázáno. Ale protože jsme odladili dílčí dotazy, než je použijeme ve větších výrazech, můžeme si být jisti odpovědí.
S klauzulí
Všimněte si, že standardní SQL poskytuje klauzuli WITH, která předznamenává příkaz SELECT a pojmenovává dílčí dotaz. (Lze jej také použít pro rekurzivní dotazy, ale to zde nepotřebujeme.)
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
Tohle je jednodušší napsat. MySQL bohužel zatím nepodporuje klauzuli WITH.
Výše uvedený SQL byl nyní testován proti IBM Informix Dynamic Server 11.70.FC2 běžícím na Mac OS X 10.7.4. Tento test odhalil problém diagnostikovaný v předběžném komentáři. SQL pro hlavní odpověď fungovalo správně, aniž by bylo nutné je měnit.