2012-03-04 24 views
9

Tôi có hai bảng (quốc gia & vịt) trong đó bảng quốc gia có mọi quốc gia trên thế giới và bảng vịt có danh sách vịt có trường country_id để liên kết với quốc gia chính.MySQL trả về hàng đầu tiên của bảng đã tham gia

Tôi đang cố gắng lấy danh sách các quốc gia có ít nhất một con vịt trong đó và với một bản ghi phù hợp từ bảng vịt cho vịt được xếp hạng cao nhất trong quốc gia đó. Cho đến nay tôi có:

SELECT * 
FROM country c 
INNER JOIN ducks d ON c.id = d.country_id 
ORDER BY c.country ASC, d.rating DESC 

Điều này trả về danh sách mọi con vịt thay vì mỗi quốc gia.

Tôi rất biết ơn nếu có ai có thể chỉ cho tôi đúng hướng ở đây. Tôi muốn làm điều đó trong SQL hơn là có một truy vấn riêng biệt cho mỗi quốc gia để kéo ra khỏi vịt được xếp hạng cao nhất.

+2

Xem: http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax- row-per-group-in-sql/ví dụ về cách thực hiện điều này. – imm

+0

Bạn muốn một chú vịt nào? chỉ là ai? – dotoree

+1

@dotoree Xếp hạng cao nhất (số lượng cao nhất từ ​​tập hợp) –

Trả lời

19
SELECT c.*, d.* 
FROM country c 
    INNER JOIN ducks d 
    ON d.id =       --- guessing the ducks Primary Key here 
     (SELECT dd.id     --- and here 
     FROM ducks dd 
     WHERE c.id = dd.country_id 
     ORDER BY dd.rating DESC 
     LIMIT 1 
     ) 

Một chỉ mục trên (country_id, rating, id) cho bảng MyISAM hoặc (country_id, rating) cho bảng InnoDB, w ould giúp đỡ.

Truy vấn này sẽ chỉ hiển thị một duck cho mỗi quốc gia, ngay cả với nhiều người có cùng xếp hạng. Nếu bạn muốn vịt có xếp hạng gắn kết xuất hiện, hãy sử dụng câu trả lời GROUP BY của @ imm.

+0

Cảm ơn bạn rằng hoạt động hoàn hảo –

+0

@ anwer của imm là tốt, quá. –

+0

+1 Rất đẹp. Có thể đạt được điều này mà không có truy vấn con nào cả? –

-1

Nhiều cơ sở dữ liệu có một số tương đương với "chọn 10 * hàng đầu từ ...". Trong mySql, cú pháp sẽ là "select * from ... limit 10".

... NHƯNG ...

Trong trường hợp này, bạn thực sự muốn "nhóm theo" và "tối đa()"!

+1

Xin chào, nhóm giới hạn kết quả, nhưng hàm MAX() chỉ hiển thị tối đa cho nhóm, nhưng phần còn lại của hàng chứa dữ liệu cho bản ghi đầu tiên được tìm thấy bởi MySQL thay vì bản ghi có xếp hạng tối đa. Đây là những gì tôi có cho đến nay: 'CHỌN c. *, D. *, MAX (d.rating) TỪ quốc gia c ĐỐI TÁC ĐỐI VỚI vịt c.id = d.country_id GROUP BY c.country ORDER BY c.country ASC, d.rating DESC' –

0

Hãy thử điều này:

SELECT c.country, MAX(d.rating) AS max_rating 
FROM country c 
JOIN ducks d ON c.id = d.country_id 
GROUP BY c.id 
ORDER BY c.country ASC 

Nếu "đánh giá cao nhất" là 1, sau đó thay đổi MAX(d.rating) để MIN(d.rating)

+0

Xin chào, điều đó rất gần vì nó trả về một quốc gia có xếp hạng tối đa, tôi đang cố gắng trả lại bản ghi tương ứng với xếp hạng tối đa đó. ví dụ: nếu tôi thay đổi dòng đầu tiên của mã thành 'SELECT c.country, d.id, d.rating, MAX (d.rating)' thì d.rating không phải lúc nào cũng bằng MAX (d.rating) nếu điều đó làm cho ý nghĩa –

+0

Vâng, đúng vậy. Tôi đã cập nhật câu trả lời. Vui lòng thử lại. –

+0

@ J.Bruni: 'HAVING' sau' ORDER BY' không phải là cú pháp hợp lệ. –

3

Bạn có thể thử:

SELECT c.*, d.* 
FROM country c 
INNER JOIN (
    SELECT d.country_id, d.id, MAX(d.rating) AS rating 
    FROM ducks d 
    GROUP BY d.country_id 
) q ON (q.country_id = c.id) 

INNER JOIN ducks d 
    ON (d.country_id, d.rating) = (q.country_id, q.rating) 
+0

Điều này chỉ cần thêm một lần nữa để hiển thị chi tiết vịt: 'INNER JOIN vịt d ON (d.country_id, d.rating) = (q.country_id, q.rating)' –

+0

@ ypercube, đúng dat. – imm

8

Bạn có thể thử chỉ cần thêm một lựa chọn tham gia, cho

SELECT c.*, d.* 
FROM country c 
INNER JOIN ducks d ON c.id = d.country_id 
LEFT JOIN ducks d2 ON d.country_id = d2.country_id AND d2.rating > d.rating 
WHERE d2.id IS NULL 
+0

Tuyệt vời! Tôi thích phiên bản này. –

+1

Và tốt hơn là nên chọn 'SELECT c. *, D. *'. Không cần bao gồm các cột 'd2. *' - sẽ là tất cả NULL. –

+1

Câu trả lời này phải là câu trả lời được chấp nhận – ScottG

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