2013-10-29 25 views
5

Truy vấn tốt nhất giữa các đề tài này là gì? Chúng xuất kết quả tương tự, mong đợi một kết quả đang làm điều kiện bên trong một số where in và một số khác bên trong một số inner join.chọn tham gia bên trong (A, B) trên A và B so với vị trí (A, B) trong (A, B) trong mysql

select uv.* from version v inner join user_version uv ON v.id=uv.version_id 
WHERE (v.number, v.master_id) IN (
select max(v.number) as number, v.master_id 
    from version v inner join user_version uv ON v.id=uv.version_id group by v.master_id); 

select * from user_version uv 
    inner join version v on v.id=uv.version_id and v.number 
    inner join (
     select uv2.user_id, max(v2.number) maxNumber, v2.master_id master_id, v2.id version_id from version v2 
     inner join user_version uv2 on v2.id=uv2.version_id group by v2.master_id) test 
    on test.master_id=v.master_id and test.maxNumber=v.number ; 

Tôi đã tạo một sqlfiddle với một ví dụ: http://sqlfiddle.com/#!2/76001/62 (Ý tưởng là để có được phiên bản lớn nhất của một thực thể "bậc thầy" liên quan đến một người dùng nhất định)

Nếu bạn có ý tưởng khác (tôi đang sử dụng mysql, vì vậy tôi không thể sử dụng chức năng cửa sổ)

Cảm ơn

+0

Nói chung, các giải pháp truy vấn con không tương quan như giải pháp thứ hai có xu hướng nhanh hơn các giải pháp thay thế của chúng. Truy vấn của bạn phức tạp hơn một chút, nhưng tôi nghĩ nguyên tắc nắm giữ. – Strawberry

Trả lời

3

Đây không phải là quá dễ dàng để trả lời câu hỏi này. Bạn nên biết một điều quan trọng: MySQL xử lý IN (<static values list>)IN (<subquery>)different queries. Đầu tiên bằng so sánh phạm vi (như .. OR = .. OR =) trong khi thứ hai bằng = ANY() - và nó không giống nhau. Vì vậy, để nói ngắn gọn: việc sử dụng IN với truy vấn con sẽ gây ra truy vấn với ANY() và MySQL sẽ không sử dụng chỉ mục cho dù ngay cả truy vấn con là độc lập và trả về danh sách giá trị tĩnh. Đáng buồn nhưng là sự thật. MySQL không thể dự đoán điều đó và vì vậy chỉ mục sẽ không được sử dụng ngay cả khi nó hiển nhiên. Nếu bạn sử dụng JOIN (tức là viết lại IN (<subquery>)) - thì MySQL sẽ sử dụng chỉ mục cho điều kiện JOIN, nếu có thể.

Hiện tại, trường hợp thứ hai có thể là khoảng JOININ khi sử dụng phân vùng. Nếu bạn sử dụng JOIN - thì thật đáng buồn - nhưng MySQL cũng không thể dự đoán các phân vùng cho JOIN trong trường hợp thông thường - và nó sẽ sử dụng toàn bộ các phân vùng cho nó. Thay thế JOIN thành IN (<static list>) sẽ thay đổi hình ảnh EXPLAIN PARTITION: MySQL sẽ chỉ sử dụng những phân đoạn đó, cần thiết để chọn giá trị từ phạm vi, được chỉ định trong mệnh đề IN. Nhưng, một lần nữa, điều này sẽ không hoạt động với IN (<subquery>). Như một kết luận - thật đáng buồn, khi chúng ta nói về cách MySQL xử lý IN truy vấn phụ - và trong trường hợp thông thường, nó không thể được thay thế bằng JOIN một cách an toàn (đó là về trường hợp phân vùng). Vì vậy, giải pháp phổ biến sẽ là: truy vấn phụ riêng biệt từ truy vấn chính trên cấp ứng dụng. Nếu chúng ta đang nói về truy vấn phụ độc lập, trả về danh sách giá trị tĩnh, đó là gợi ý tốt nhất - sau đó bạn có thể thay thế danh sách giá trị đó thành IN(<static list>) và nhận lợi ích: MySQL sẽ sử dụng chỉ mục cho nó, và nếu chúng ta nói về phân vùng thực sự cần thiết từ chúng sẽ được sử dụng.

+0

là bạn nói rằng yêu cầu đầu tiên sẽ không sử dụng chỉ mục trên master_id/number và thứ hai, lựa chọn phụ sẽ trả lại tất cả kết quả khớp với lựa chọn cho mỗi dòng, không có bộ lọc trên test.master_id = v. master_id condition? (ý tưởng PARTITION không thực sự rõ ràng đối với tôi trong trường hợp này) – Quentin

+0

Thứ nhất sẽ không sử dụng chỉ mục cho truy vấn con 'IN' –

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