2012-05-22 26 views
5

Nói rằng tôi có một số SELECT tuyên bố:Tìm số hàng trong một loại dựa trên id hàng, sau đó tìm các nước láng giềng

SELECT id, name FROM people 
    ORDER BY name ASC; 

Tôi có một vài triệu hàng trong bảng people và mệnh đề ORDER BY có thể được nhiều phức tạp hơn những gì tôi đã hiển thị ở đây (có thể hoạt động trên một tá cột).

Tôi chỉ lấy một tập nhỏ các hàng (nói các hàng 1..11) để hiển thị chúng trong giao diện người dùng. Bây giờ, tôi muốn giải quyết các vấn đề sau:

  1. Tìm số hàng có số id nhất định.
  2. Hiển thị 5 mục trước và 5 mục sau hàng có id nhất định.

Vấn đề 2 rất dễ giải quyết khi tôi đã giải quyết vấn đề 1, sau đó tôi có thể sử dụng thứ gì đó như thế này nếu tôi biết mục tôi đang tìm có số hàng 1000 trong tập hợp kết quả được sắp xếp (đây là Firebird phương ngữ SQL):

SELECT id, name FROM people 
    ORDER BY name ASC 
    ROWS 995 TO 1005; 

tôi cũng biết rằng tôi có thể tìm ra rank của một hàng bằng cách đếm tất cả các hàng mà đến trước người tôi đang tìm kiếm, nhưng điều này có thể dẫn đến WHERE khoản rất dài với tấn ORAND trong điều kiện. Và tôi phải làm điều này nhiều lần. Với dữ liệu thử nghiệm của tôi, điều này mất hàng trăm mili giây, ngay cả khi sử dụng các cột được lập chỉ mục đúng cách, quá chậm.

Có một số phương tiện để đạt được điều này bằng cách sử dụng một số tính năng SQL: 2003 (chẳng hạn như row_number được hỗ trợ trong Firebird 3.0)? Tôi là không có cách nào một guru SQL và tôi cần một số con trỏ ở đây. Tôi có thể tạo chế độ xem được lưu trong bộ nhớ cache trong đó kết quả sẽ bao gồm chỉ mục xếp hạng/xếp hạng hàng/dày đặc không?

+0

quá khó để trả lời mà không có thông tin về loại giao diện người dùng. Web? Máy tính để bàn? Dòng lệnh? Giao diện người dùng thoại ;-) – rstrelba

+0

Tôi đang hiển thị danh sách những người trong ứng dụng dành cho máy tính để bàn; kể từ khi bộ sưu tập là rất lớn, tôi chỉ lấy hàng cho những người phù hợp với chế độ xem của danh sách. Người dùng có một thanh cuộn cho phép cô di chuyển đến bất kỳ điểm nào trong danh sách và làm cho nó làm mới nội dung của nó như thể nó thực sự được lấp đầy với hàng triệu hàng. –

+0

có bao nhiêu tham số bổ sung trong bộ lọc của chế độ xem? – rstrelba

Trả lời

3

Firebird xuất hiện để hỗ trợ các chức năng cửa sổ (được gọi là chức năng phân tích trong Oracle). Vì vậy, bạn có thể làm như sau:

Để tìm "hàng" số một liên tiếp với một id đưa ra:

select id, row_number() over (partition by NULL order by name, id) 
from t 
where id = <id> 

này giả định của id là duy nhất.

Để giải quyết vấn đề thứ hai:

select t.* 
from (select id, row_number() over (partition by NULL order by name, id) as rownum 
     from t 
    ) t join 
    (select id, row_number() over (partition by NULL order by name, id) as rownum 
     from t 
     where id = <id> 
    ) tid 
    on t.rownum between tid.rownum - 5 and tid.rownum + 5 

tôi có thể đề nghị một cái gì đó khác, tuy nhiên, nếu bạn có thể chỉnh sửa cấu trúc bảng. Hầu hết các cơ sở dữ liệu cung cấp khả năng thêm một cột tăng tự động khi một hàng được chèn vào. Nếu hồ sơ của bạn không bao giờ bị xóa, máy chủ này có thể làm bộ đếm của bạn, đơn giản hóa truy vấn của bạn.

+0

cảm ơn bạn đã đề xuất của bạn. Tôi đã hy vọng một cái gì đó dọc theo dòng của những gì bạn đề nghị trong giải pháp đầu tiên của bạn. Và có, cột 'id' của tôi chứa các giá trị duy nhất. –

+0

Tôi không hiểu ý bạn là gì bằng cách sửa đổi cấu trúc bảng; về cơ bản, 'id' đã là cột tăng tự động. Vấn đề là, thứ tự của các hàng phụ thuộc vào thứ tự trong câu lệnh 'SELECT'. Cột bổ sung có thể giúp tôi như thế nào? Tôi đã bỏ lỡ một cái gì đó? –

+0

Nếu bạn không xóa các hàng trong bảng, bạn chỉ có thể sử dụng "trong đó id giữa - 5 và + 5". Điều này sẽ loại bỏ phép tính row_number(). Nói cách khác, giải pháp cho vấn đề của bạn sẽ chỉ là tự tham gia. –

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