2012-05-22 9 views
5

decir que tengo algo de SELECT declaración:encontrar en una ordenación basada en el corredor de Identificación, y luego encontrar sus vecinos

SELECT id, name FROM people 
    ORDER BY name ASC; 

que tienen unos pocos millones de filas de la tabla people y la cláusula ORDER BY puede ser mucho más complejo que lo que he mostrado aquí (posiblemente operando en una docena de columnas).

Recupero solo un pequeño subconjunto de las filas (digamos las filas 1..11) para mostrarlas en la interfaz de usuario. Ahora, me gustaría resolver los siguientes problemas:

  1. Encuentra el número de una fila con un dado id.
  2. Muestra los 5 elementos antes y los 5 elementos después de una fila con un id dado.

Problema 2 es fácil de resolver de una vez he resuelto el problema 1, ya que entonces puedo usar algo como esto si sé que el tema que estaba buscando tiene fila de números 1000 en el conjunto de resultados ordenados (este es el Firebird lenguaje SQL):

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

también sé que puedo encontrar el rank de una fila contando todas las filas, que se presentan ante el que estoy buscando, pero esto puede llevar a muy largas WHERE cláusulas con toneladas de OR y AND en la condición. Y tengo que hacer esto varias veces. Con mis datos de prueba, esto lleva cientos de milisegundos, incluso cuando se utilizan columnas correctamente indexadas, lo cual es demasiado lento.

¿Hay alguna forma de lograr esto utilizando algunas características SQL 2003 (como row_number compatibles con Firebird 3.0)? De ninguna manera soy un gurú de SQL y necesito algunos consejos aquí. ¿Podría crear una vista en caché donde el resultado incluiría un índice de rango/fila densa/fila?

+0

demasiado difícil de responder sin información sobre el tipo de IU. ¿Web? ¿Escritorio? ¿Línea de comando? Voice UI ;-) – rstrelba

+0

Estoy mostrando una lista de personas en una aplicación de escritorio; dado que la colección es enorme, solo busco las filas de las personas que encajan en la ventana gráfica de la lista. El usuario tiene una barra de desplazamiento que le permite moverse a cualquier punto de la lista y hacer que actualice su contenido como si realmente estuviera lleno de millones de filas. –

+0

¿cuántos parámetros adicionales en el filtro de la ventana gráfica? – rstrelba

Respuesta

3

Firebird parece ser compatible con funciones de ventana (llamadas funciones analíticas en Oracle). Así que usted puede hacer lo siguiente:

para encontrar el número "fila" de un una fila con un identificador dado:

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

Esto supone que los identificadores son únicos.

Para resolver el segundo problema:

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 

que podría sugerir otra cosa, sin embargo, si se puede modificar la estructura de tabla. La mayoría de las bases de datos ofrecen la posibilidad de agregar una columna de autoincremento cuando se inserta una fila. Si sus registros nunca se eliminan, esto puede servir como su contador, simplificando sus consultas.

+0

gracias por su sugerencia. Esperaba algo parecido a lo que sugieres en tu primera solución. Y sí, mi columna 'id' contiene valores únicos. –

+0

No entiendo lo que quiere decir con la modificación de la estructura de la tabla; básicamente, 'id' ya es una columna de incremento automático. El problema es que el orden de las filas depende del orden en la instrucción 'SELECT'. ¿Cómo podría ayudarme una columna adicional? ¿Me he perdido algo? –

+0

Si no elimina las filas de la tabla, puede usar "where id between - 5 and + 5". Esto eliminaría el cálculo row_number(). En otras palabras, la solución a su problema sería simplemente unirse a sí mismo. –

Cuestiones relacionadas