2015-01-02 36 views
7

Nie wiem, jak nazwać ten problem. Popraw mnie, jeśli masz lepsze słowa.MySQL wybierz najlepsze wiersze z tymi samymi wartościami warunkowymi

Mam dwie tabele, Użytkownicy i posty.

użytkowników:

id | username | password | ... 

postów:

id | author_id | title | content | ... 

Teraz chcę do listy "najbardziej aktywnych" użytkowników - użytkowników, którzy napisali najwięcej posty. A konkretnie chcę uzyskać wynik top 10.

SELECT u.username, COUNT(p.id) AS count 
FROM Posts p, Users u 
WHERE u.id=p.author_id 
GROUP BY p.author_id 
ORDER BY count DESC 
LIMIT 10; 

Mogę uzyskać oczekiwany wynik. Jednak ranking może nie być "fair", jeśli niektórzy użytkownicy mają taką samą liczbę postów.

przykład może uzyskać wyniki takie jak:

User 1 | 14 
User 2 | 13 
... 
User 9 | 4 
User 10 | 4 

tu, tam są rzeczywiście wiele więcej użytkowników, którzy mają 4 posty.

Tak więc top 10 może nie być dokładnie wynikiem 10. Jak mogę uzyskać bardziej "uczciwy" wynik, który zawiera dodatkowe wiersze użytkowników, którzy mają 4 posty?

+1

Bardzo ciekawy problem :) Może potrzebować zmiennej w zapytaniu, zobaczmy, co ludzie wymyślą. –

+0

Czy chcesz dodać kilka przykładowych danych, abyśmy mogli zobaczyć kilka fajnych skrzypiec? –

+0

@Hanky ​​웃 Panky I uprościł moje dane tutaj. Jeśli chcesz przetestować, możesz wypróbować przypadek "top 2", w którym możesz łatwo sfałszować niektóre dane. – mrmoment

Odpowiedz

4

Jest to dobre rozwiązanie, myślę: trzeba podkwerendę wiedzieć ile poczta ma 10 miejsce w twojej najlepsza dziesiątka. Następnie należy użyć zewnętrznej kwerendy, aby wyodrębnić użytkowników przy użyciu niemal tego postcount.

SELECT u.username, COUNT(p.id) AS count 
FROM Posts p 
JOIN Users u ON u.id = p.author_id 
GROUP BY p.author_id 
HAVING COUNT(p.id) >= 
(
    SELECT COUNT(p.id) AS count 
    FROM Posts p 
    JOIN Users u ON u.id = p.author_id 
    GROUP BY p.author_id 
    ORDER BY count DESC 
    LIMIT 9, 1 
) 
ORDER BY count DESC 
+2

'LIMIT 1, 9'? –

+0

Myślę, że powinno to być "LIMIT 9, 1". – Barmar

+0

Przepraszam, moje złe! Edytowane – Jean

0

Spróbuj tego:

SELECT username, PostCount 
FROM (SELECT username, PostCount, IF(@PostCount = @PostCount:=PostCount, @idx:[email protected]+1, @Idx:=1) AS idx 
     FROM (SELECT u.username, COUNT(p.id) AS PostCount 
      FROM Posts p 
      INNER JOIN Users u ON u.id=p.author_id 
      GROUP BY p.author_id 
      ) AS A, (SELECT @PostCount:=0, @Idx:=1) AS B 
     ORDER BY PostCount DESC 
    ) AS A 
WHERE idx <= 10; 
+0

Zapytanie 3-poziomowe? Coś jest nie tak ... – Jean

+1

Wykonujesz podzapytanie dla każdego autora, by wyodrębnić liczbę postów, i próbujesz pogrupować użytkownika według ich liczby postów i myślę, że to trochę bzdura. – Jean

3
nie

Może najlepszym rozwiązaniem

select u.username, COUNT(p.id) AS count 
FROM Posts p 
join Users u on u.id = p.author_id 
GROUP BY p.author_id 
having COUNT(p.id) in 
(
    SELECT COUNT(p.id) 
    FROM Posts p 
    join Users u on u.id = p.author_id 
    GROUP BY p.author_id 
    ORDER BY count DESC 
    LIMIT 10  
) 
ORDER BY count DESC 
+3

Czy nie powinien to być "POSIADAJĄCY COUNT (p .id) IN'? Jeśli użyjesz '> =', podzapytanie musi zwrócić pojedynczą wartość. Możesz zmienić podzapytanie, aby użyć 'LIMIT 9, 1'. – Barmar

+1

Nie powinieneś używać 'DISTINCT'. – Barmar

+0

Zaimplementowałem sugestię @Barmar w mojej odpowiedzi, uważam, że jest to właściwa odpowiedź: – Jean