2015-07-05 14 views
5

Tôi đang cố gắng tìm ra ngôn ngữ mà người dùng trả lời nhiều nhất và trả về user_id, số language_id họ trả lời nhiều nhất và số lần họ trả lời.Sử dụng MAX() và COUNT() trong cùng một truy vấn

tôi bắt đầu bởi SELECT ing một bảng/tiểu bảng trả về các kết quả này:

Table: `sub-selected` 
`user_id` `language_id` `answers` 
    1    1    1 
    2    1    1 
    1    2    5 
    2    2    2 
    1    4    3 
    1    5    1 

bảng này trả về user_id, các language_id, và bao nhiêu lần rằng language_id đã được trả lời bởi người sử dụng. Tôi đã từng truy vấn này để có được nó:

SELECT t1.user_id, t2.to_language_id, COUNT(t2.to_language_id) as answers 
FROM translation_results as t1 
LEFT JOIN translations as t2 
ON t2.translation_id = t1.translation_id 
GROUP BY t2.to_language_id, t1.user_id 

Cấu trúc bảng là:

Table: `translations` 
`translation_id` `from_phrase_id` `to_language_id` 

Table: `translation_results` 
`translation_id` `result_id` PRI-AI `user_id` 

Các translations cửa hàng bảng tất cả các bản dịch yêu cầu và xem translation_results bảng lưu trữ các câu trả lời cho những bản dịch và tương ứng user_id .

Vì vậy, để tổng hợp bàn và để có được những user_id, hầu hết họ đã trả lời language_id, và bao nhiêu lần họ đã trả lời trong language_id đó, tôi đã sử dụng:

SELECT t1.user_id, t1.to_language_id, MAX(t1.answers) 
FROM (
    //The sub-table 
    SELECT t1.user_id, t2.to_language_id, COUNT(t2.to_language_id) as answers 
    FROM translation_results as t1 
    LEFT JOIN translations as t2 
    ON t2.translation_id = t1.translation_id 
    GROUP BY t2.to_language_id, t1.user_id 
) as t1 
GROUP BY t1.user_id, t1.to_language_id 

Nhưng điều này không thu gọn bảng vào cấu trúc mong muốn và thay vào đó trả về:

Table: `sub-selected` 
`user_id` `language_id` `answers` 
    1    1    1 
    1    2    5 
    1    4    3 
    1    5    1 
    2    1    1 
    2    2    2 

tôi biết nó bị ảnh hưởng bởi nhóm bằng của two clauses, nhưng sau đó nếu tôi chỉ nhóm bởi user_id và không bao gồm to_language_id trong các cột được lựa chọn của tôi, tôi không thể biết được tôn trọng e language_id được trả lời nhiều nhất. Tôi cũng đã cố gắng truy vấn phụ và một vài tham gia, nhưng tôi thấy tôi liên tục cần phải sử dụng MAX(t1.answers) bất kể trong các cột được chọn và do đó phá hủy hy vọng của tôi nắm bắt các group by chính xác. Làm cách nào tôi có thể thu gọn truy vấn chính xác thay vì có group by tìm tất cả các kết hợp MAX() độc đáo của user_idto_language_id?

+0

Hi bạn có thể tạo [SQL Fiddle] (http://sqlfiddle.com/) với một số dữ liệu và thêm vào câu hỏi của bạn mong muốn đầu ra? tnx –

Trả lời

1

Để nhận được:

các user_id, họ đã trả lời hầu hết language_id, và bao nhiêu lần họ trả lời trong language_id rằng

bạn có thể sử dụng các biến:

SELECT user_id, language_id, answers 
FROM (
    SELECT user_id, language_id, answers, 
     @rn:= IF(@uid = user_id, 
        IF(@uid:=user_id, @rn:[email protected]+1, @rn:[email protected]+1), 
        IF(@uid:=user_id, @rn:=1, @rn:=1)) AS rn 
    FROM (SELECT t1.user_id, t2.to_language_id AS language_id, 
       COUNT(t2.to_language_id) as answers  
     FROM translation_results as t1 
     LEFT JOIN translations as t2 
      ON t2.translation_id = t1.translation_id 
     GROUP BY t2.to_language_id, t1.user_id 
     ) t 
    CROSS JOIN (SELECT @rn:=0, @uid:=0) AS vars 
    ORDER BY user_id, answers DESC 
) s 
WHERE s.rn = 1 

Có là một hạn chế tuy nhiên trong truy vấn trên: nếu có nhiều hơn một language_id chia sẻ cùng một m số câu trả lời tối ưu cho user_id, sau đó chỉ một câu trả lời sẽ được trả lại.

Demo here

Một cách khác, là sử dụng bạn truy vấn gấp đôi so với một bảng có nguồn gốc:

SELECT t1.user_id, language_id, t1.answers 
FROM (SELECT t1.user_id, t2.to_language_id AS language_id, 
      COUNT(t2.to_language_id) as answers 
     FROM translation_results as t1 
     LEFT JOIN translations as t2 
     ON t2.translation_id = t1.translation_id 
     GROUP BY t2.to_language_id, t1.user_id) t1 
INNER JOIN (  
    SELECT user_id, MAX(answers) AS answers 
    FROM (SELECT t1.user_id, t2.to_language_id, 
       COUNT(t2.to_language_id) as answers 
     FROM translation_results as t1 
     LEFT JOIN translations as t2 
      ON t2.translation_id = t1.translation_id 
     GROUP BY t2.to_language_id, t1.user_id 
     ) t 
    GROUP BY user_id) t2 
ON t1.user_id = t2.user_id AND t1.answers = t2.answers 

truy vấn này không có giới hạn của truy vấn trước đó, nhưng có thể sẽ kém hiệu quả so với trước đó.

Demo here

+0

Câu trả lời tuyệt vời, bản trình diễn tuyệt vời và giải thích tốt. Cảm ơn bạn –

0

Nếu tôi undestood câu hỏi của bạn, bạn nên xác định một bảng tạm thời hoặc có nguồn gốc với kết quả của subquery, cho phép gọi là sub_selected, sau đó bạn nên làm:

SELECT t1.user_id, t1.to_language_id, answers 
FROM sub_selected as t1 
WHERE t1.answers = 
    (SELECT MAX(answers) 
    FROM sub_selected t2 
    WHERE t1.user_id = t2.user_id and t1.to_language_id = t2.language_id) 
Các vấn đề liên quan