top only first db2 limit ibm-midrange

only - Equivalente de LIMIT para DB2



select top 1 db2 (9)

¿Cómo se hace LIMIT en DB2 para iSeries?

Tengo una tabla con más de 50,000 registros y quiero devolver registros de 0 a 10,000, y registros de 10,000 a 20,000.

Sé que en SQL escribes LIMIT 0,10000 al final de la consulta de 0 a 10,000 y LIMIT 10000,10000 al final de la consulta de 10000 a 20,000

Entonces, ¿cómo se hace esto en DB2? ¿Cuál es el código y la sintaxis? (se agradece el ejemplo de consulta completa)


Aquí está la solución que se me ocurrió:

select FIELD from TABLE where FIELD > LASTVAL order by FIELD fetch first N rows only;

Al inicializar LASTVAL en 0 (o '''' para un campo de texto), luego establecerlo en el último valor en el conjunto más reciente de registros, esto pasará a través de la tabla en fragmentos de N registros.


Desarrollado este método:

NECESITA una tabla que tenga un valor único que pueda ordenarse.

Si quiere filas de 10,000 a 25,000 y su tabla tiene 40,000 filas, primero necesita obtener el punto inicial y las filas totales:

int start = 40000 - 10000;

int total = 25000 - 10000;

Y luego pasa estos por código a la consulta:

SELECT * FROM (SELECT * FROM schema.mytable ORDER BY userId DESC fetch first {start} rows only ) AS mini ORDER BY mini.userId ASC fetch first {total} rows only


El soporte para OFFSET y LIMIT se agregó recientemente a DB2 para i 7.1 y 7.2. Necesita los siguientes niveles de grupo de DB PTF para obtener este soporte:

  • SF99702 nivel 9 para IBM i 7.2
  • SF99701 nivel 38 para IBM i 7.1

Consulte aquí para obtener más información: documentation OFFSET y LIMIT, Wiki DB2 for i Enhancement


Estas son las opciones disponibles:

DB2 has several strategies to cope with this problem. You can use the "scrollable cursor" in feature. In this case you can open a cursor and, instead of re-issuing a query you can FETCH forward and backward. This works great if your application can hold state since it doesn''t require DB2 to rerun the query every time. You can use the ROW_NUMBER() OLAP function to number rows and then return the subset you want. This is ANSI SQL You can use the ROWNUM pseudo columns which does the same as ROW_NUMBER() but is suitable if you have Oracle skills. You can use LIMIT and OFFSET if you are more leaning to a mySQL or PostgreSQL dialect.


Hay 2 soluciones para paginar eficientemente en una tabla de DB2:

1 - la técnica que usa la función row_number () y la cláusula OVER que se ha presentado en otra publicación ("SELECT row_number () OVER (ORDER BY ...)"). En algunas mesas grandes, noté a veces una degradación de las actuaciones.

2 - la técnica que usa un cursor desplazable. La implementación depende del lenguaje utilizado. Esa técnica parece más robusta en las tablas grandes.

Presenté las 2 técnicas implementadas en PHP durante un seminario el próximo año. La diapositiva está disponible en este enlace: http://gregphplab.com/serendipity/uploads/slides/DB2_PHP_Best_practices.pdf

Lo siento pero este documento solo está en francés.


Prueba esto

SELECT * FROM ( SELECT T.*, ROW_NUMBER() OVER() R FROM TABLE T ) WHERE R BETWEEN 10000 AND 20000


También debe considerar la cláusula OPTIMIZE FOR n ROWS. Más detalles sobre todo esto en la documentación de LUW de DB2 en las Pautas para restringir el tema de instrucciones SELECT :

  • La cláusula OPTIMIZE FOR declara la intención de recuperar solo un subconjunto del resultado o dar prioridad a recuperar solo las primeras filas. El optimizador puede elegir planes de acceso que minimicen el tiempo de respuesta para recuperar las primeras filas.

Usando FETCH FIRST [n] ROWS ONLY :

http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.db29.doc.perf/db2z_fetchfirstnrows.htm

SELECT LASTNAME, FIRSTNAME, EMPNO, SALARY FROM EMP ORDER BY SALARY DESC FETCH FIRST 20 ROWS ONLY;

Para obtener rangos, debe usar ROW_NUMBER() (desde v5r4) y usar eso dentro de la cláusula WHERE : (robado desde aquí: http://www.justskins.com/forums/db2-select-how-to-123209.html )

SELECT code, name, address FROM ( SELECT row_number() OVER ( ORDER BY code ) AS rid, code, name, address FROM contacts WHERE name LIKE ''%Bob%'' ) AS t WHERE t.rid BETWEEN 20 AND 25;


La solución de @ elcool es una idea inteligente, pero necesitas saber el número total de filas (¡que incluso puede cambiar mientras estás ejecutando la consulta!). Así que propongo una versión modificada, que lamentablemente necesita 3 subconsultas en lugar de 2:

select * from ( select * from ( select * from MYLIB.MYTABLE order by MYID asc fetch first {last} rows only ) I order by MYID desc fetch first {length} rows only ) II order by MYID asc

donde {last} debe reemplazarse con el número de fila del último registro que necesito y {length} debe reemplazarse por el número de filas que necesito, calculado como la last row - first row + 1 .

Por ejemplo, si quiero filas de 10 a 25 (totalmente 16 filas), {last} será 25 y {length} será 25-10 + 1 = 16.