2013-01-25 38 views
5

Tôi có cơ sở dữ liệu trong đó mọi người gửi phiếu bầu cho những người ở những nơi khác nhau. Vào một thời điểm nhất định, tôi muốn tìm ra ai có nhiều phiếu bầu nhất ở mỗi nơi. (Một người có thể được biểu quyết tại hai nơi khác nhau)Cách nhận hàng tối đa của mỗi nhóm?

Đây là SQL tôi có cho đến nay:

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 

mà mang lại cho tôi kết quả này:

enter image description here

Bây giờ, đây là những các hàng tôi thực sự muốn:

enter image description here

Điều gì thiếu trong truy vấn của tôi để tôi có thể nhận được điều này?

  • Tôi muốn có một kết quả cho mỗi địa điểm. Vì vậy, tôi sẽ chỉ thấy các địa điểm riêng biệt, với userVotedId đã nhận được nhiều phiếu bầu nhất.

  • Trong trường hợp hòa, người chiến thắng ngẫu nhiên sẽ làm!

+0

những gì bạn nhận được và những gì bạn muốn là giống hệt nhau. Vì vậy, truy vấn của bạn hoạt động! – cha

+0

@cha Tôi nghĩ như vậy, nhưng vấn đề là để loại bỏ các placeid đôi = 51. Có thể có nhiều cách dễ hiểu hơn để chỉ ra điều này thay vì bốn hộp màu đỏ gập ghềnh ;-) – KekuSemau

+0

Nếu bạn đang cố gắng để có được đầu hàng dựa trên cnt khi bạn đã thêm nhóm theo placeID của kết quả của bạn, đây là một vấn đề khó khăn hơn lần đầu tiên xuất hiện. Trong SQL Server, tôi nghĩ rằng bạn có thể thực hiện điều này với APPLY, nhưng điều đó không được hỗ trợ (?) Trong MySQL. – Matthew

Trả lời

3

Có vẻ như bạn cần một tổng hợp nhiều hơn nữa. Sử dụng các MAX() tổng hợp về giá trị cnt của bạn và 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 

Lưu ý: tôi đã thay đổi truy vấn của bạn để sử dụng cú pháp JOIN thay cho dấu phẩy giữa các bảng.

Chỉnh sửa, dựa trên nhận xét của bạn sau nên làm việc:

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 

Xem SQL Fiddle with Demo

Kết quả là:

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

Chỉnh sửa # 2, nếu bạn muốn có một số ngẫu nhiên trả lại nếu có cà vạt, thì bạn có thể sử dụng biến người dùng:

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 

Xem SQL Fiddle with Demo

+0

nope ... không hoạt động: http://imgur.com/8cpl8pO –

+0

Bạn có muốn tối đa theo địa điểm không? Hay bạn cũng muốn userid? – Taryn

+0

Tôi muốn có một kết quả cho mỗi địa điểm. Vì vậy, tôi sẽ chỉ thấy các địa điểm riêng biệt, với userVotedId đã nhận được nhiều phiếu bầu nhất. –

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

điều này chỉ trả lại một giá trị ... –

+0

@omegatai - Tôi đã bỏ qua mệnh đề nhóm, câu trả lời được cập nhật. – MuhammadHani

+0

không, vẫn không hoạt động ... http://imgur.com/nQ2PA2u –

1

Để đơn giản, tôi gọi thử truy vấn của bạn:

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 

Đây là Fiddle.

BTW - Kiểm tra =:

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 

Chúc may mắn.

--edit - theo yêu cầu, đây là mã cuối cùng:

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 - Tôi đã sử dụng bản trình diễn này với SQL của tôi và nó đã hoạt động - đây là câu hỏi: http://sqlfiddle.com/#!2/23bd7/6 – sgeddes

+0

Tôi vừa nhận ra giải pháp của bạn là không 't khá làm việc. Xem ở đây: http://sqlfiddle.com/#!2/6a8f4/1 –

Các vấn đề liên quan