2012-05-04 41 views
7

Tôi có truy vấn nơi tôi muốn chọn tất cả người dùng thích một nhóm nghệ sĩ nhất định. Ngoài ra còn có một số tiêu chuẩn WHERE khác về quốc gia, vv Đây là những gì lược đồ trông như thế nào.Truy vấn Postgresql - Sắp xếp theo kết quả truy vấn con

  users      favourite_artists    artists 

+----------+------------+ +-----------+------------+ +--------+--------+ 
| id | country | | user_id | artist_id | | id | name | 
+----------+------------+ +-----------+------------+ +--------+--------+ 
|  1 |  gb  | |  1  |  6  | | 1 | Muse | 
|  2 |  gb  | |  1  |  5  | | 2 | RATM | 
|  3 |  us  | |  1  |  3  | | 3 | ABBA | 
|  4 |  us  | |  2  |  3  | | 4 | U2 | 
+----------+------------+ +-----------+------------+ +--------+--------+ 

Tôi muốn sắp xếp chúng theo số lượng nghệ sĩ mà họ thích. Tôi cũng muốn bao gồm những người dùng không thích bất kỳ nghệ sĩ nào nhưng phù hợp với tiêu chí WHERE. Tập kết quả mong đợi sẽ trông như thế nào.

+--------+---------------+----------------+ 
| id | country | match_count | 
+--------+---------------+----------------+ 
| 6 |  gb  |  4  | 
| 9 |  gb  |  4  | 
| 2 |  gb  |  3  | 
| 1 |  gb  |  2  | 
| 5 |  gb  |  0  | 
| 4 |  gb  |  0  | 
+--------+---------------+----------------+ 

Tôi đã cố gắng để làm điều đó bằng một subquery để có được những match_count và đặt hàng bằng cách đó, nhưng nó thực hiện khá chậm vì vậy tôi nghĩ có muốn phải là một cách tốt hơn.

SELECT users.id, users.country 
    (SELECT COUNT(*) FROM favourite_artists 
    WHERE user_id = users.id AND artist_id IN (1,3,4,9)) AS match_count   
    FROM "users" 
    WHERE users.country = 'gb' 
    ORDER BY match_count DESC; 

Tôi đang sử dụng Postgresql 9.0.7. Có suy nghĩ gì không?

Trả lời

6

Truy vấn của bạn đang thực hiện một truy vấn con cho mỗi hàng trong users. Các truy vấn như vậy được gọi là "truy vấn con tương quan" và hiệu suất của chúng, khá dễ hiểu, hút.

Thay vào đó bạn muốn có một gia:

SELECT users.id, users.country, count(artist_id) as match_count 
FROM users 
LEFT JOIN favourite_artists ON user_id = users.id AND artist_id IN (1,3,4,9) 
WHERE users.country = 'gb' 
GROUP BY 1, 2 
ORDER BY 3 DESC; 

Truy vấn này sẽ nhận được hàng tham gia cho đến nay hiệu quả hơn, giả sử bạn có một chỉ mục trên favourite_artists(user_id) - hoặc tốt hơn là một multi-column indexfavourite_artists(user_id, artist_id).

+1

+1 cho phần giới thiệu rất hay. :) –

+1

Dựa vào vị trí trong mệnh đề ORDER BY vi phạm lý thuyết quan hệ, giữ nguyên thứ tự của các trường trong tập kết quả không được xác định. Thay vào đó, tôi đề xuất "ORDER BY match_count". –

+1

@JoelFinkel Nó không "vi phạm" bất cứ điều gì. Thứ tự các cột được xác định * trong truy vấn *, vì vậy đóng gói là nguyên vẹn. Tốt rồi. Tôi không thể hiểu tại sao một số người có quần lót của họ trong một loạt các vấn đề này cực kỳ tầm thường mà làm cho hoàn toàn không có sự khác biệt nào cho kết quả hoặc bất cứ điều gì khác cho vấn đề đó. Có cá lớn hơn để chiên. Trên thực tế, có * cá * để chiên - đây không phải là một con cá. Không có gì. – Bohemian

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