2008-09-18 10 views
6

Mam tabelę z wynikami gier, umożliwiającą wiele wierszy na konto: scores (id, score, accountid). Chcę listę 10 najlepszych identyfikatorów wyników i ich wyników.Pobierz jeden wiersz na identyfikator konta z listy

Czy możesz podać instrukcję sql, aby wybrać 10 najlepszych wyników, ale tylko jeden wynik na identyfikator konta?

Dzięki!

+0

Czy robimy twoje zadanie domowe? – paulwhit

+4

Praca domowa czy nie, pytanie jest dobre IMHO, ponieważ prosty DISTINCT nie zadziała i trzeba go połączyć z funkcją agregacji - problem, który natknąłem się na kilka razy, a rozwiązanie na SO przyniosłoby korzyści wszystkim. –

Odpowiedz

2

Najpierw ograniczyć wybór do najwyższego wyniku dla każdego identyfikatora konta. Następnie zdobądź dziesięć pierwszych wyników.

SELECT TOP 10 AccountId, Score 
FROM Scores s1 
WHERE AccountId NOT IN 
    (SELECT AccountId s2 FROM Scores 
    WHERE s1.AccountId = s2.AccountId and s1.Score > s2.Score) 
ORDER BY Score DESC 
+0

Okazało się, że to wydaje się lepsze, ponieważ wybiera cały wiersz. Drugie maks. Zapytanie zostało dodane tylko do wyniku maks. Do losowego wiersza dla każdego konta. – Kenzie

+0

Poprawiono: SELECT * FROM wyniki s1 GDZIE accountid NOT IN (SELECT accountid OD zdobywa s2 GDZIE s1.accountid = s2.accountid i s1.score Kenzie

+2

Tylko pozostały problemem w przypadku tego zapytania otrzymuję więcej niż jeden wiersz na konto, gdy konto ma więcej niż jedno wystąpienie najwyższego wyniku. Więc jeśli accoundid 6 ma wyniki 50, 75, 40, 75 to zapytanie zwraca oba wiersze z wynikiem 75. – Kenzie

2

Spróbuj tego:

select top 10 username, 
       max(score) 
from usertable 
group by username 
order by max(score) desc 
+1

Czy "top 10" jest nowy? Nie pamiętam tego wcześniej? – zigdon

+0

zależy od DBMS - był nowy dla SQL Server w 2000 roku – Danimal

+0

Powinienem był podać mysql. Limit zrobił lewę. Dzięki. – Kenzie

1

PostgreSQL posiada DISTINCT ON klauzuli, która działa w ten sposób:

SELECT DISTINCT ON (accountid) id, score, accountid 
FROM scoretable 
ORDER BY score DESC 
LIMIT 10; 

Nie sądzę, że to norma SQL chociaż, więc należy się spodziewać innych baz danych, aby to zrobić różnie.

4
select username, max(score) from usertable group by username order by max(score) desc limit 10; 
+0

ten potrzebuje "desc" na zamówienie przez – Magnar

+0

Zaktualizowano, dziękuję. – zigdon

1
SELECT accountid, MAX(score) as top_score 
FROM Scores 
GROUP BY accountid, 
ORDER BY top_score DESC 
LIMIT 0, 10

To powinno działać dobrze w mysql. Możliwe, że zamiast tego zamówienia będziesz musiał użyć opcji "ZAMÓW POPULARNĄ (wynik) DESC" zamiast tego zamówienia - nie mam pod ręką referencji SQL.

0

Wierzę, że PostgreSQL (co najmniej 8,3) będzie wymagać, aby wyrażenia DISTINCT ON były zgodne z początkowymi wyrażeniami ORDER BY. TO ZNACZY. nie możesz użyć DISTINCT ON (accountid), gdy masz ORDER BY score DESC. Aby rozwiązać ten problem, należy dodać go do ORDER BY:

SELECT DISTINCT ON (accountid) * 
FROM scoretable 
ORDER BY accountid, score DESC 
LIMIT 10; 

Stosując tę ​​metodę można wybrać wszystkie kolumny w tabeli. Zwróci on tylko 1 wiersz na konto, nawet jeśli istnieją powielone wartości "maksimum" dla wyniku.

To było dla mnie przydatne, ponieważ nie znalazłem maksymalnego wyniku (co jest łatwe do zrobienia przy pomocy funkcji max()), ale dla ostatniego czasu wprowadzono wynik dla konta.