2013-01-25 14 views
5

Mam bazę danych, w której ludzie przesyłają głosy do osób w różnych miejscach. W danym momencie chcę się dowiedzieć, kto ma najwięcej głosów w każdym miejscu. (Osoba może być wybrany w dwóch różnych miejscach)Jak uzyskać maksymalny rząd każdej grupy?

To SQL mam tak daleko:

SELECT placeId, userVotedId, cnt 
FROM 
    (SELECT uvo.userVotedId, p.placeId, count(*) as cnt 
    FROM users as u, users_votes as uvo, places as p 
    WHERE u.userId = uvo.userVotedId 
     AND p.placeId = uvo.placeId 
    GROUP BY userVotedId, placeId) 
AS RESULT 

który daje mi ten wynik:

enter image description here

Teraz są to wiersze NAPRAWDĘ chcę:

enter image description here

Czego brakuje w moim zapytaniu, więc mogę to zdobyć?

  • Chcę jeden wynik na miejsce. Więc powinienem zobaczyć tylko odrębne placeIds, z userVotedId, który otrzymał najwięcej głosów.

  • W przypadku remisu, losowy zwycięzca zrobi!

+0

co masz i co chcesz są identyczne. Twoje zapytanie działa! – cha

+0

@cha Myślałem tak samo, ale chodzi o to, aby wyeliminować podwójne miejsce = 51. Mogły być bardziej uchwytne sposoby na wskazanie tego zamiast czterech wyboistych czerwonych skrzynek ;-) – KekuSemau

+0

Jeśli próbujesz zdobyć górę wiersz oparty na cnt, gdy dodatkowo pogrupujesz według placeID wyników, jest to trudniejszy problem niż na początku. W SQL Server myślę, że można to osiągnąć za pomocą APLIKACJI, ale to nie jest obsługiwane (?) W MySQL. – Matthew

Odpowiedz

3

Wygląda na to trzeba jeszcze jeden agregat. Użyj kruszywo MAX() na wartości cnt i GROUP BY placeId, userVotedId:

SELECT placeId, userVotedId, max(cnt) 
FROM 
(
    SELECT uvo.userVotedId, p.placeId, count(*) as cnt 
    FROM users as u 
    INNER JOIN users_votes as uvo 
    ON u.userId = uvo.userVotedId 
    INNER JOIN places as p 
    ON p.placeId = uvo.placeId 
    GROUP BY userVotedId, placeId 
) AS RESULT 
GROUP BY placeId, userVotedId 

Uwaga: Zmieniłem zapytanie do korzystania JOIN składni zamiast przecinków między tabelami.

Edycja, na podstawie Twojego komentarza następujące powinny działać:

select total.uservotedid, 
    total.placeid, 
    total.cnt 
from 
(
    SELECT uvo.userVotedId, p.placeId, count(*) as cnt 
    FROM users as u 
    INNER JOIN users_votes as uvo 
    ON u.userId = uvo.userVotedId 
    INNER JOIN places as p 
    ON p.placeId = uvo.placeId 
    GROUP BY userVotedId, placeId 
) total 
inner join 
(
    select max(cnt) Mx, placeid 
    from 
    (
    SELECT uvo.userVotedId, p.placeId, count(*) as cnt 
    FROM users as u 
    INNER JOIN users_votes as uvo 
     ON u.userId = uvo.userVotedId 
    INNER JOIN places as p 
     ON p.placeId = uvo.placeId 
    GROUP BY userVotedId, placeId 
) mx 
    group by placeid 
) src 
    on total.placeid = src.placeid 
    and total.cnt = src.mx 

Zobacz SQL Fiddle with Demo

Wynikiem jest:

| USERVOTEDID | PLACEID | CNT | 
------------------------------- 
|   65 |  11 | 1 | 
|   67 |  13 | 1 | 
|   67 |  25 | 1 | 
|   67 |  51 | 2 | 

Edit # 2, jeśli chcesz liczbę losową w przypadku remisu można użyć zmiennych użytkownika:

select uservotedid, 
    placeid, 
    cnt 
from 
(
    select total.uservotedid, 
    total.placeid, 
    total.cnt, 
    @rownum := case when @prev = total.placeid then @rownum+1 else 1 end rownum, 
    @prev := total.placeid pplaceid 
    from 
    (
    SELECT uvo.userVotedId, p.placeId, count(*) as cnt 
    FROM users as u 
    INNER JOIN users_votes as uvo 
     ON u.userId = uvo.userVotedId 
    INNER JOIN places as p 
     ON p.placeId = uvo.placeId 
    GROUP BY userVotedId, placeId 
) total 
    inner join 
    (
    select max(cnt) Mx, placeid 
    from 
    (
     SELECT uvo.userVotedId, p.placeId, count(*) as cnt 
     FROM users as u 
     INNER JOIN users_votes as uvo 
     ON u.userId = uvo.userVotedId 
     INNER JOIN places as p 
     ON p.placeId = uvo.placeId 
     GROUP BY userVotedId, placeId 
    ) mx 
    group by placeid 
) src 
    on total.placeid = src.placeid 
    and total.cnt = src.mx 
    order by total.placeid, total.uservotedid 
) src 
where rownum = 1 
order by placeid, uservotedid 

Zobacz SQL Fiddle with Demo

+0

nie ... nie działa: http://imgur.com/8cpl8pO –

+0

Czy chcesz maksimum według miejsca? A może chcesz również identyfikatora użytkownika? – Taryn

+0

Chcę jeden wynik na miejsce. Więc powinienem zobaczyć tylko odrębne placeIds, z userVotedId, który otrzymał najwięcej głosów. –

1
SELECT placeId, userVotedId, MAX(cnt) 
    FROM (SELECT uvo.userVotedId, p.placeId, count(*) AS cnt 
      FROM users as u, users_votes as uvo, places as p 
      WHERE u.userId = uvo.userVotedId AND p.placeId = uvo.placeId 
      GROUP BY userVotedId, placeId) AS RESULT 
    GROUP BY placeId 
+0

to zwraca tylko jedną wartość ... –

+0

@omegatai - Brakuje mi klauzuli grupującej, odpowiedź zaktualizowana. – MuhammadHani

+0

nie, wciąż nie działa ... http://imgur.com/nQ2PA2u –

1

Dla uproszczenia, zadzwoniłem test Zapytanie:

SELECT * 
FROM Test T JOIN (
SELECT t.placeId, Max(t.cnt) maxcnt 
FROM Test t 
GROUP BY t.placeId) T2 ON T.placeId = T2.placeId and T.cnt = T2.maxcnt 

Oto Fiddle.

BTW - Test =:

SELECT uvo.userVotedId, p.placeId, count(*) as cnt 
    FROM users as u 
    INNER JOIN users_votes as uvo 
    ON u.userId = uvo.userVotedId 
    INNER JOIN places as p 
    ON p.placeId = uvo.placeId 
    GROUP BY userVotedId, placeId 

Powodzenia.

--edit - zgodnie z wnioskiem, tutaj jest ostatni kod:

SELECT * 
FROM (SELECT uvo.userVotedId, p.placeId, count(*) AS cnt 
      FROM users as u, users_votes as uvo, places as p 
      WHERE u.userId = uvo.userVotedId AND p.placeId = uvo.placeId 
      GROUP BY userVotedId, placeId) T JOIN (
SELECT t.placeId, Max(t.cnt) maxcnt 
FROM (SELECT uvo.userVotedId, p.placeId, count(*) AS cnt 
      FROM users as u, users_votes as uvo, places as p 
      WHERE u.userId = uvo.userVotedId AND p.placeId = uvo.placeId 
      GROUP BY userVotedId, placeId) t 
GROUP BY t.placeId) T2 ON T.placeId = T2.placeId and T.cnt = T2.maxcnt 
+0

@omegatai - Użyłem tego demo z moim SQL i zadziałało - oto skrzypce: http://sqlfiddle.com/#!2/23bd7/6 – sgeddes

+0

Właśnie zdałem sobie sprawę, że twoje rozwiązanie nie działa nie działa. Patrz tutaj: http://sqlfiddle.com/#!2/6a8f4/1 –

Powiązane problemy