2012-05-22 9 views
5

сказать, что у меня есть некоторые SELECT заявление:Найти номер строки в каком-то на основе идентификатора строки, а затем найти свои сосед

SELECT id, name FROM people 
    ORDER BY name ASC; 

У меня есть несколько миллионов строк в people таблице и оговорке ORDER BY может быть много более сложный, чем то, что я показал здесь (возможно, работает на дюжине столбцов).

Я извлекаю только небольшое подмножество строк (например, строки 1..11), чтобы отображать их в пользовательском интерфейсе. Теперь я хотел бы решить следующие проблемы:

  1. Найти номер строки с заданным id.
  2. Показать 5 предметов до и 5 предметов после строки с заданным id.

Задача 2 легко решить, как только я решил проблему 1, так как я могу после этого использовать что-то вроде этого, если я знаю, что этот пункт я искал имеет строки номер 1000 в отсортированном наборе результатов (это Firebird SQL диалект):

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

Я также знаю, что я могу найти rank из строки путем подсчета всех строк, которые приходят к одному из них я искал, но это может привести к очень длинным WHERE предложениям с тонн OR и AND в состоянии. И я должен делать это неоднократно. С моими тестовыми данными это занимает сотни миллисекунд, даже при использовании правильно проиндексированных столбцов, что слишком медленно.

Есть ли способ достичь этого, используя некоторые функции SQL: 2003 (например, row_number, поддерживаемый Firebird 3.0)? Я никоим образом не являюсь гуру SQL, и мне нужны некоторые указатели. Могу ли я создать кешированный вид, в котором результат будет включать в себя индекс ранга/плотного ранга/строки?

+0

слишком сложно ответить без информации о типе интерфейса. Веб? Desktop? Командная строка? Voice UI ;-) – rstrelba

+0

Я показываю список людей в настольном приложении; поскольку коллекция огромна, я получаю только строки для лиц, которые вписываются в окно просмотра списка. Пользователь имеет полосу прокрутки, которая позволяет ей перемещаться в любую точку списка и обновлять ее содержимое, как если бы оно действительно заполнялось миллионами строк. –

+0

сколько дополнительных параметров в фильмах видового экрана? – rstrelba

ответ

3

Firebird, похоже, поддерживает функции окна (называемые аналитическими функциями в Oracle). Таким образом, вы можете сделать следующее:

Чтобы найти «строки» число в строке с заданным идентификатором:

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

Это предполагает, идентификаторы уникальны.

Чтобы решить вторую проблему:

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 

я мог бы предложить что-то другое, хотя, если вы можете изменить структуру таблицы. В большинстве баз данных имеется возможность добавлять столбец автоинкремента при вставке строки. Если ваши записи никогда не удаляются, это может служить сервером как ваш счетчик, упрощая ваши запросы.

+0

Благодарю вас за ваше предложение. Я надеялся что-то вроде того, что вы предлагаете в своем первом решении. И да, мой столбец 'id' содержит уникальные значения. –

+0

Я не понимаю, что вы подразумеваете, изменяя структуру таблицы; в основном, 'id' уже является столбцом автоматического увеличения. Проблема в том, что порядок строк зависит от порядка в инструкции 'SELECT'. Как могла бы помочь мне дополнительная колонка? Я что-то пропустил? –

+0

Если вы не удаляете строки из таблицы, вы можете просто использовать «где id между - 5 и + 5». Это устранит вычисление row_number(). Другими словами, решение вашей проблемы было бы просто самосоединением. –