2013-04-27 39 views
6

Tôi tự hỏi đặc biệt về PostgreSQL. Đưa ra ví dụ sau đây contrived:Thứ tự trong truy vấn phụ có được bảo đảm để được giữ nguyên không?

SELECT name FROM 
    (SELECT name FROM people WHERE age >= 18 ORDER BY age DESC) p 
LIMIT 10 

Các tên được trả về từ truy vấn bên ngoài được bảo đảm theo thứ tự cho truy vấn bên trong?

+4

Do tối ưu hóa, nó có lẽ sẽ trở lại chúng theo thứ tự ... nhưng theo tiêu chuẩn SQL, thứ tự của truy vấn phụ không ảnh hưởng đến truy vấn chính. – Godeke

Trả lời

9

Không, đặt thứ tự bằng trong truy vấn bên ngoài:

SELECT name FROM 
    (SELECT name, age FROM people WHERE age >= 18) p 
ORDER BY p.age DESC 
LIMIT 10 

Các nội (sub) truy vấn trả về một kết quả-set. Nếu bạn đặt thứ tự ở đó, thì tập hợp kết quả trung gian được truyền từ truy vấn bên trong (phụ) đến truy vấn bên ngoài, được đảm bảo được sắp xếp theo cách bạn chỉ định, nhưng không có thứ tự trong truy vấn bên ngoài, kết quả -set được tạo bằng cách xử lý bộ kết quả truy vấn bên trong, không được đảm bảo để được sắp xếp theo bất kỳ cách nào.

+0

Cái quái gì ?! Nếu nó từ chối làm điều đó tại sao không chỉ ném một lỗi cú pháp? – Adamantish

+0

Truy vấn bên trong (phụ) trả về một tập kết quả. Nếu bạn đặt hàng ở đó, thì kết quả trung gian được chuyển từ truy vấn bên trong (sub) tới truy vấn bên ngoài, được đảm bảo được sắp xếp theo cách bạn chỉ định, nhưng tập kết quả được tạo bởi truy vấn bên ngoài, bằng cách xử lý truy vấn bên trong đó resultset, không phải. –

+0

Điểm tinh tế thú vị. Tôi ngầm sẽ không mong đợi thứ tự của một tập hợp kết quả đã ra lệnh được thay đổi trừ khi tham gia vào một kết quả thứ hai nhưng có thể thấy làm thế nào có thể khó đoán được người tối ưu. – Adamantish

0

không được bảo đảm để được theo thứ tự, mặc dù khi bạn chạy nó, bạn có thể thấy rằng nó thường theo thứ tự.

Bạn nên đặt thứ tự bằng trên truy vấn chính

SELECT name FROM 
(SELECT name FROM people WHERE age >= 18) p 
ORDER BY p.age DESC LIMIT 10 
4

Đối với trường hợp đơn giản, @Charles query là hiệu quả nhất.

Tổng quát hơn, bạn có thể sử dụng chức năng window row_number() để thực hiện bất kỳ thứ tự mà bạn muốn truy vấn chính, bao gồm:

  • trật tự của cột không trong SELECT danh sách các subquery và do đó không thể tái sản xuất
  • đặt hàng tùy ý của đồng nghiệp theo tiêu chí ORDER BY. Postgres sẽ sử dụng lại cùng một thứ tự tùy ý trong hàm cửa sổ trong vòng truy vấn phụ. (Nhưng không phải thứ tự ngẫu nhiên thực sự từ random() chẳng hạn!)
    Nếu bạn không muốn giữ lại thứ tự sắp xếp tùy ý của các đồng nghiệp từ truy vấn phụ, hãy sử dụng rank() để thay thế.

này cũng có thể nói chung là vượt trội với các truy vấn phức tạp hoặc nhiều lớp truy vấn:

SELECT name 
FROM (
    SELECT name, row_number OVER (ORDER BY <same order by criteria>) AS rn 
    FROM people 
    WHERE age >= 18 
    ORDER BY <any order by criteria> 
    ) p 
ORDER BY p.rn 
LIMIT 10; 
Các vấn đề liên quan