Query selectivo de rows en Oracle

La tarea consiste en obtener una consulta selectiva de filas en una query de oracle, es decir, si una query nos trae 50 filas como resultado, nuestro objetivo consiste en rescatar solo desde la fila 20 a la 30.
¿Es posible realizar esta tarea? Si, es posible usando una tecnica llamada PAGINACION, la cual hace uso de la “pseudocolumna” Rownum.

La tecnica es simple y consiste en el uso de tres querys anidadas.

Supongamos una consulta del tipo:

SELECT TOPONIMO_CALLE, NOMBRE_COMUNA, ID_CALLE, FECHA, ID_TIPO_CALLE, USUARIO
FROM T_TOPONIMO_CALLE

TOPONIMO_CALLE                    NOMBRE_COMUNA     ID_CALLE     FECHA                   ID_TIPO_CALLE     USUARIO
 --------------------------------  ----------------  -----------  ----------------------  ----------------  ----------
 ALMIRANTE BIRD                    RECOLETA          21093        20-11-2007 12:00:00 AM  3                 CORREOS
 AVENIDA BERNARDO OHIGGINS         SAN ANTONIO       96841        20-11-2007 12:00:00 AM  0                 CORREOS
 AVENIDA BERNARDO OHIGGINS         CALAMA            78106        20-11-2007 12:00:00 AM  0                 CORREOS
 AVENIDA BERNARDO OHIGGINS         ESTACION CENTRAL  43295        20-11-2007 12:00:00 AM  2                 CORREOS
 AVENIDA BERNARDO OHIGGINS         RANCAGUA          37235        20-11-2007 12:00:00 AM  2                 CORREOS
 AVENIDA BERNARDO OHIGGINS         SAN FELIPE        86496        20-11-2007 12:00:00 AM  0                 CORREOS
 AVENIDA BERNARDO OHIGGINS         SANTIAGO          38967        20-11-2007 12:00:00 AM  2                 CORREOS
 AVENIDA BERNARDO OHIGGINS         TALAGANTE         76611        20-11-2007 12:00:00 AM  0                 CORREOS
 AVENIDA CARDENAL JOSE MARIA CARO  RECOLETA          43327        20-11-2007 12:00:00 AM  2                 CORREOS
 AVENIDA LATORRE                   CALERA            79714        20-11-2007 12:00:00 AM  0                 CORREOS
 AVENIDA LIBERTADOR OHIGGINS       ESTACION CENTRAL  43295        20-11-2007 12:00:00 AM  2                 CORREOS
 AVENIDA OHIGGINS                  CURACAVI          88553        20-11-2007 12:00:00 AM  0                 CORREOS
 AVENIDA OHIGGINS                  CALAMA            78106        20-11-2007 12:00:00 AM  0                 CORREOS
 AVENIDA OHIGGINS                  TALAGANTE         76611        20-11-2007 12:00:00 AM  0                 CORREOS
 AVENIDA PACIFICO                  VALPARAISO        29379        20-11-2007 12:00:00 AM  2                 CORREOS
 BARROS ARANA                      TEMUCO            33049        20-11-2007 12:00:00 AM  2                 CORREOS
 JOSE MANUEL BORGONO               MAIPU             39975        20-11-2007 12:00:00 AM  2                 CORREOS
 OHIGGINS                          CALERA            79719        20-11-2007 12:00:00 AM  0                 CORREOS
 OHIGGINS                          TALCA             55748        20-11-2007 12:00:00 AM  0                 CORREOS
 OHIGGINS PONIENTE                 CHIGUAYANTE       115825       20-11-2007 12:00:00 AM  0                 CORREOS    

 20 record(s) selected [Fetch MetaData: 0/ms] [Fetch Data: 16/ms] 

 [Executed: 13-05-09 04:09:22 PM CLT ] [Execution: 0/ms]

Como se puede observar nuestra query nos devuelve 20 rows, pero nosotros queremos rescatar solo desde la row 10 a la 15 [10,15].
Para lograrlo primero debemos obtener la numeracion de cada row, lo cual se logra con Rownum.

SELECT ROWNUM RNUM, TOPONIMO_CALLE, NOMBRE_COMUNA, ID_CALLE, FECHA, ID_TIPO_CALLE, USUARIO
FROM
    (SELECT TOPONIMO_CALLE, NOMBRE_COMUNA, ID_CALLE, FECHA, ID_TIPO_CALLE, USUARIO
    FROM T_TOPONIMO_CALLE)
WHERE ROWNUM <= 15

 RNUM     TOPONIMO_CALLE                    NOMBRE_COMUNA     ID_CALLE     FECHA                   ID_TIPO_CALLE     USUARIO
 -------  --------------------------------  ----------------  -----------  ----------------------  ----------------  ----------
 1        ALMIRANTE BIRD                    RECOLETA          21093        20-11-2007 12:00:00 AM  3                 CORREOS
 2        AVENIDA BERNARDO OHIGGINS         SAN ANTONIO       96841        20-11-2007 12:00:00 AM  0                 CORREOS
 3        AVENIDA BERNARDO OHIGGINS         CALAMA            78106        20-11-2007 12:00:00 AM  0                 CORREOS
 4        AVENIDA BERNARDO OHIGGINS         ESTACION CENTRAL  43295        20-11-2007 12:00:00 AM  2                 CORREOS
 5        AVENIDA BERNARDO OHIGGINS         RANCAGUA          37235        20-11-2007 12:00:00 AM  2                 CORREOS
 6        AVENIDA BERNARDO OHIGGINS         SAN FELIPE        86496        20-11-2007 12:00:00 AM  0                 CORREOS
 7        AVENIDA BERNARDO OHIGGINS         SANTIAGO          38967        20-11-2007 12:00:00 AM  2                 CORREOS
 8        AVENIDA BERNARDO OHIGGINS         TALAGANTE         76611        20-11-2007 12:00:00 AM  0                 CORREOS
 9        AVENIDA CARDENAL JOSE MARIA CARO  RECOLETA          43327        20-11-2007 12:00:00 AM  2                 CORREOS
 10       AVENIDA LATORRE                   CALERA            79714        20-11-2007 12:00:00 AM  0                 CORREOS
 11       AVENIDA LIBERTADOR OHIGGINS       ESTACION CENTRAL  43295        20-11-2007 12:00:00 AM  2                 CORREOS
 12       AVENIDA OHIGGINS                  CURACAVI          88553        20-11-2007 12:00:00 AM  0                 CORREOS
 13       AVENIDA OHIGGINS                  CALAMA            78106        20-11-2007 12:00:00 AM  0                 CORREOS
 14       AVENIDA OHIGGINS                  TALAGANTE         76611        20-11-2007 12:00:00 AM  0                 CORREOS
 15       AVENIDA PACIFICO                  VALPARAISO        29379        20-11-2007 12:00:00 AM  2                 CORREOS    

 15 record(s) selected [Fetch MetaData: 0/ms] [Fetch Data: 16/ms] 

 [Executed: 13-05-09 04:14:56 PM CLT ] [Execution: 0/ms]

Esta es la primera parte de la tecnica donde se usan dos select anidados para generar la columna virtual RNUM y para filtrar el maximo de rows a obtener. Como en nuestro ejemplo nuestro rango es de la row 10 a la 15, entoces con el uso de Rownum se obtiene hasta la row 15.
Ahora debemos obtener el limite inferior, es decir, de la row 10 en adelante, para lo cual debemos anidar otro select, condicionando nuestra pseudocolumna RNUM.

SELECT ROWNUM RNUM, TOPONIMO_CALLE, NOMBRE_COMUNA, ID_CALLE, FECHA, ID_TIPO_CALLE, USUARIO
FROM
    (SELECT ROWNUM RNUM, TOPONIMO_CALLE, NOMBRE_COMUNA, ID_CALLE, FECHA, ID_TIPO_CALLE, USUARIO
    FROM
        (SELECT TOPONIMO_CALLE, NOMBRE_COMUNA, ID_CALLE, FECHA, ID_TIPO_CALLE, USUARIO
        FROM T_TOPONIMO_CALLE)
    WHERE ROWNUM <= 15)
WHERE RNUM >= 10

 RNUM     TOPONIMO_CALLE               NOMBRE_COMUNA     ID_CALLE     FECHA                   ID_TIPO_CALLE     USUARIO
 -------  ---------------------------  ----------------  -----------  ----------------------  ----------------  ----------
 1        AVENIDA LATORRE              CALERA            79714        20-11-2007 12:00:00 AM  0                 CORREOS
 2        AVENIDA LIBERTADOR OHIGGINS  ESTACION CENTRAL  43295        20-11-2007 12:00:00 AM  2                 CORREOS
 3        AVENIDA OHIGGINS             CURACAVI          88553        20-11-2007 12:00:00 AM  0                 CORREOS
 4        AVENIDA OHIGGINS             CALAMA            78106        20-11-2007 12:00:00 AM  0                 CORREOS
 5        AVENIDA OHIGGINS             TALAGANTE         76611        20-11-2007 12:00:00 AM  0                 CORREOS
 6        AVENIDA PACIFICO             VALPARAISO        29379        20-11-2007 12:00:00 AM  2                 CORREOS    

 6 record(s) selected [Fetch MetaData: 0/ms] [Fetch Data: 0/ms] 

 [Executed: 13-05-09 04:20:03 PM CLT ] [Execution: 0/ms]

Con estos select anidados y el uso del rownum podemos realizar la tecnica de paginacion en oracle.
Suerte!!

2 comentarios to this post.

  1. Publicado por Anónimo en Junio 23, 2009 at 2:14 am

    El rownum no funciona cuando hay un ORDER BY ya que la ordenación se ejecute a posteriori de asignar el rownum.

  2. Publicado por vitocosan en Junio 23, 2009 at 9:07 am

    Podrías probar la consulta agregándole el order by, ya que en mi caso funciono perfectamente:

    SELECT ROWNUM RNUM, TOPONIMO_CALLE, NOMBRE_COMUNA, ID_CALLE, FECHA, ID_TIPO_CALLE, USUARIO
    FROM
        (SELECT ROWNUM RNUM, TOPONIMO_CALLE, NOMBRE_COMUNA, ID_CALLE, FECHA, ID_TIPO_CALLE, USUARIO
        FROM
            (SELECT TOPONIMO_CALLE, NOMBRE_COMUNA, ID_CALLE, FECHA, ID_TIPO_CALLE, USUARIO
            FROM T_TOPONIMO_CALLE
            ORDER BY NOMBRE_COMUNA)
        WHERE ROWNUM <= 15)
    WHERE RNUM >= 10
    

Contestar a esta entrada