2008-10-14 7 views
5

Tôi đang tìm cách để xếp hàng số hàng trong tập hợp kết quả (không phải bảng). Về bản chất, tôi bắt đầu với một truy vấn như sau:Kỹ thuật Pure-SQL để tự động đánh số hàng trong tập hợp kết quả

SELECT id, name FROM people WHERE name = 'Spiewak' 

Các id s rõ ràng không phải một chuỗi đúng (ví dụ 1, 2, 3, 4). Những gì tôi cần là một cột khác trong tập kết quả có chứa các số tự động này. Tôi sẵn sàng sử dụng một hàm SQL nếu tôi có, nhưng tôi thà làm điều đó mà không cần sử dụng phần mở rộng trên thông số ANSI.

Nền tảng là MySQL, nhưng kỹ thuật phải là nền tảng chéo nếu có thể (do đó mong muốn tránh các phần mở rộng không chuẩn).

Trả lời

9

Để có một số lượng hàng có ý nghĩa bạn cần phải đặt kết quả của bạn. Sau đó, bạn có thể làm một cái gì đó như thế này:

SELECT id, name 
    , (SELECT COUNT(*) FROM people p2 WHERE name='Spiewak' AND p2.id <= p1.id) AS RowNumber 
FROM people p1 
WHERE name = 'Spiewak' 
ORDER BY id 

Lưu ý rằng mệnh đề WHERE của truy vấn phụ cần phải phù hợp với mệnh đề WHERE hoặc khóa chính từ truy vấn chính ORDER BY của truy vấn chính.

Máy chủ SQL có cấu trúc ROW_NUMBER() OVER để đơn giản hóa điều này, nhưng tôi không biết liệu MySQL có bất kỳ điều gì đặc biệt để giải quyết nó hay không.


Từ bài của tôi ở đây đã được chấp nhận như là câu trả lời, tôi muốn cũng để gọi ra phản ứng Dan Goldstein, mà là rất giống nhau trong cách tiếp cận nhưng sử dụng lệnh JOIN thay vì một truy vấn phụ và thường sẽ thực hiện tốt

+1

Đó là thông minh, nhưng hiệu suất phải là HORRIBLE. Không phải là tôi đang nói có một câu trả lời tốt hơn, chỉ cần rùng mình ở O (n^2) của nó. –

+0

Wow! Điều đó rất thông minh. Tôi thậm chí không biết bạn có thể sử dụng truy vấn phụ để xác định các trường res trong thời trang đó. –

+0

Đồng ý rằng hiệu suất có thể tốt hơn, nhưng nếu bạn bị giới hạn ở ansi thì đó là những gì bạn phải làm. Đôi khi mọi người sẽ tính toán trước các kết quả này để tăng tốc độ. –

2

Không có cách nào tiêu chuẩn ANSI để thực hiện việc này mà tôi biết.

Trong SQL Server, bạn có hàm ROW_NUMBER() có thể được sử dụng và trong Oracle, có một cột giả ROWNUM.

Trong MySQL, có this technique

+0

Có thể anh ấy thích ROW_NUMBER() để RANK() cho điều này, nhưng khi anh ấy sử dụng MySQL/Ansi, đây là điểm tranh luận. –

7

Một ý tưởng đó là khá hiệu quả nhưng là ANSI SQL sẽ để đếm số hàng với một id nhỏ hơn khớp với cùng một tiêu chí. Tôi đã không thử nghiệm SQL này và nó có thể sẽ không hoạt động, nhưng một cái gì đó như:

SELECT id, name, sub.lcount 
FROM people outer 
JOIN (SELECT id, COUNT(id) lcount FROM people WHERE name = 'Spiewak' AND id < outer.id GROUP BY id) sub on outer.id = sub.id 
WHERE name = 'Spiewak' 
+0

Về cơ bản giống như những gì tôi đã đăng, nhưng JOIN có thể nhanh hơn truy vấn phụ cho hầu hết các trường hợp. –

+0

Ồ, bạn vẫn cần một thứ tự rõ ràng bằng hàng đợi bên ngoài của bạn hoặc điều này có thể trả lại kết quả được sắp xếp khác với truy vấn. –

-1

Đối với máy chủ SQL, hãy kiểm tra hàm RANK.

2

Trong oracle cơ sở dữ liệu duy nhất tôi biết những gì bạn muốn làm là làm một phụ chọn trên các dữ liệu

tức

select rownum, id , blah, blah 
from (
select id, name FROM people WHERE name = 'Spiewak' 
) 

khái niệm cơ bản được rằng rownum sẽ được đánh giá trên tập kết quả được trả về từ lựa chọn bên trong.

Tôi hy vọng điều này có thể hướng bạn đến giải pháp mà bạn có thể sử dụng.

1

Tôi biết đây là một chủ đề cũ, nhưng tôi vừa mới tìm câu trả lời này. Tôi đã thử truy vấn của Dan Goldstein trong MySQL, nhưng nó không hoạt động như được viết bởi vì 'bên ngoài' là một từ dành riêng. Sau đó, tôi nhận thấy rằng nó vẫn còn sử dụng một truy vấn phụ, anyways.

Vì vậy, tôi đã tìm ra một phiên bản sử dụng JOIN, nhưng NO phụ truy vấn:

SELECT SUM(IF(p1.id > p2.id, 0, 1)) AS `row`, p2.id, p2.name 
    FROM people p1 JOIN people p2 ON p1.name = p2.name 
    WHERE p1.name = 'Spiewak' 
    GROUP BY p2.id 

này đã làm việc cho tôi trong MySQL 5.1. Đối với MySQL, có vẻ như là đủ để GROUP BY p2.id. Một ORDER BY p2.id rõ ràng có thể được thêm vào cuối truy vấn, nhưng tôi cũng nhận được kết quả tương tự.