2008-09-25 12 views
7

Làm cách nào tôi có thể nhận được kết quả N cho một số nhóm trong số truy vấn oracle.Nhận kết quả hàng đầu cho mỗi nhóm (trong Oracle)

Ví dụ, đưa ra bảng sau:

|--------+------------+------------| 
| emp_id | name  | occupation | 
|--------+------------+------------| 
|  1 | John Smith | Accountant | 
|  2 | Jane Doe | Engineer | 
|  3 | Jack Black | Funnyman | 
|--------+------------+------------| 

Có rất nhiều hàng hơn với nghề. Tôi muốn nhận được ba nhân viên (cho phép nói) từ mỗi nghề nghiệp.

Có cách nào để thực hiện việc này mà không cần sử dụng truy vấn con không?

Trả lời

11

Điều này tạo ra những gì bạn muốn và nó không sử dụng các tính năng SQL cụ thể của nhà cung cấp như TOP N hoặc RANK().

SELECT e.name, e.occupation 
FROM emp AS e 
    LEFT OUTER JOIN emp AS e2 
    ON (e.occupation = e2.occupation AND e.emp_id <= e2.emp_id) 
GROUP BY e.emp_id 
HAVING COUNT(*) <= 3 
ORDER BY e.occupation; 

Trong ví dụ này, nó cung cấp cho ba nhân viên có giá trị emp_id thấp nhất cho mỗi nghề nghiệp. Bạn có thể thay đổi các thuộc tính được sử dụng trong so sánh bất bình đẳng, để làm cho nó cung cấp cho các nhân viên hàng đầu theo tên, hoặc bất cứ điều gì.

+3

Tôi nghĩ rằng điều này sẽ không thành công trên mệnh đề GROUP BY. Không có chức năng tổng hợp trong danh sách lựa chọn của bạn. – jop

+1

Tôi đã kiểm tra truy vấn này trước khi đăng. SQL không yêu cầu các hàm tổng hợp để sử dụng GROUP BY. –

2

Tôi không chắc chắn điều này là rất hiệu quả, nhưng có thể là một nơi bắt đầu?

select * 
from people p1 
    join people p2 
     on p1.occupation = p2.occupation 
    join people p3 
     on p1.occupation = p3.occupation 
     and p2.occupation = p3.occupation 
where p1.emp_id != p2.emp_id 
    and p1.emp_id != p3.emp_id 

Điều này sẽ cung cấp cho bạn các hàng chứa 3 nhân viên riêng biệt cùng nghề nghiệp. Thật không may, nó sẽ cung cấp cho bạn TẤT CẢ sự kết hợp của những người.

Bạn có thể chia sẻ điều này không?

28

Tôi không có một thể hiện oracle tiện dụng ngay bây giờ vì vậy tôi đã không kiểm tra này:

select * 
from (select emp_id, name, occupation, 
     rank() over (partition by occupation order by emp_id) rank 
     from employee) 
where rank <= 3 

Dưới đây là một liên kết trên các công trình như thế nào rank: http://www.psoug.org/reference/rank.html

+2

didnt ông chỉ định mà không có một subquery ...? – AviD

+1

Có, nhưng anh ấy có thể có nghĩa là "không sử dụng truy vấn phụ chọn từ cùng một bảng một lần nữa". Giải pháp này sử dụng truy vấn phụ nhưng chỉ truy cập vào bảng một lần. –

2

thử nghiệm điều này trong SQL Server (và nó sử dụng subquery)

select emp_id, name, occupation 
from employees t1 
where emp_id IN (select top 3 emp_id from employees t2 where t2.occupation = t1.occupation) 

chỉ làm một TRÌNH TỰ bởi trong subquery cho phù hợp với nhu cầu của bạn

2

Thêm ROWNUM để xếp hạng:

select * from 
     (select emp_id, name, occupation,rank() over (partition by occupation order by emp_id,RowNum) rank 
         from employee) 
     where rank <= 3