Vous êtes sur la page 1sur 10

25/06/12

: Utilizando funciones analiticas en Oracle para paginar

Usuario:

Clave: Recordarme

Conctate Olvid mi contrasea Registrarse

Home Bienvenida Registrarse Sobre la wiki


Conctate Login as Usuario: Clave:

UTILIZANDO FUNCIONES ANALITICAS EN ORACLE PARA PAGINAR

Utilizando funciones analiticas en Oracle para paginar Sobre el uso de ROW_NUMBER, RANK y DENSE_RANK Por: Sergio Rafael Gianazza en: Dom 21 de Ene, 2007 22:08 EST (27237 Lecturas)
(15612 bytes)

Recordarme (para 2 horas) Conctate [ Registrarse | Olvid mi contrasea ] Usuarios en lnea 10 usuarios en lnea

Traduccion del Articulo de la revista Oracle Magazine EL siguiente artculo es una traduccin aproximada de un artculo publicado en el nmero de Enero/Febrero de 2007 de la revista Oracle.

Sobre queries de paginado y top-n


Top-N query
Otra mantera de escribir queries del tipo top-n (similar al LIMIT de MySQL o usar "set rowcount" en SQL Server para limitar el numero de registros devueltos por un query) es usar la funcion analitica ROW_NUMBER. Esta se comporta de manera similar a la pseudocolumna ROWNUM pero es mas flexible y posee mas capacidades. Especificamente, podremos usar ROW_NUMBER para obtener los "primeros-n registros por algun set de atributos). Veamos los que ROW_NUMBER puede hacer. Aqui hay un ejemplo de query usando ROW_NUMBER para asignar un numero incremental a cada columna en la tabla EMP despues de haber ordenado por SAL DESC.

SL slc eae sl Q> eet nm, a, 2 3 4 5 6/ EAE NM ----KN IG FR OD SOT CT JNS OE . . . JMS AE SIH MT
www.epidataconsulting.com/tikiwiki/tiki-read_article.php?articleId=64

rwnme( o_ubr) oe (re b slds)r vr odr y a ec n fo ep rm m odrb slds re y a ec

SL A -50 00 30 00 30 00 27 95

R N 1 2 3 4

90 5 80 0

1 3 1 4
1/10

25/06/12

: Utilizando funciones analiticas en Oracle para paginar

1 rw slce. 4 os eetd

Entonces, ROW_NUMBER permite asignar facilmente un numero incremental luego de ordenar, pero a primera vista, no pareciera que permita devolver las primeras n filas>

SL slc eae sl Q> eet nm, a, 2 3 4 5 6 7 8 9/ rwnme( o_ubr) * ERRa ln 6 RO t ie : OA343 wno fntosaentalwdhr R-08: idw ucin r o loe ee rwnme( o_ubr) oe (re b slds)r vr odr y a ec n fo ep rm m wee hr rwnme( o_ubr) oe (re b slds)< 3 vr odr y a ec = odrb slds re y a ec

El problema es que las funciones analiticas son evaluadas despues de la clausula WHERE, por lo que no pueden ser utilizadas en la clausula WHERE. Esto no es realmente un problema, porque utilizando las vistas inline se puede utilizar un predicado ROW_NUMBER luego de ser asignado. Por ejemplo:

SL slc * Q> eet 2 3 4 5 7 ) 8 weer < 3 hr n = 9 odrb slds re y a ec 1 0 / EAE NM ----KN IG SOT CT FR OD 30 00 30 00 SL A -50 00 2 3 1 R N fo ( rm slc eae sl eet nm, a, rwnme( o_ubr) oe (re b slds)r vr odr y a ec n

6 fo ep rm m

3rw slce. os eetd

www.epidataconsulting.com/tikiwiki/tiki-read_article.php?articleId=64

2/10

25/06/12

: Utilizando funciones analiticas en Oracle para paginar

Lo anterior muestra como ejecutar un query top-n usando ROW_NUMBER y tambien muestra un problema con los queries del tipo top-n. Si miran el resultado, veran dos filas con el resultado 3000. Que pasaria si ,en la tabla EMP, tres personas, en vez de dos, tuvieran un salario de 3000? El resultado obtenido por el query anterior seria ambiguo - obtendiramos tres registros, pero esos tres registros seran, de alguna manera, aleatorios. Por ejemplo:

SLudt ep Q>pae m 2 stsl30 e a=00 3 weeeae'MT' hr nm=SIH; 1rwudtd o pae. SL slc * Q> eet 2 3 4 5 6 7 8 9 ) weer < 3 hr n = odrb slds re y a ec fo ( rm slc eae sl eet nm, a, rwnme( o_ubr) oe(re b slds)r vrodr y a ec n fo ep rm m

1 / 0 EAE NM ----KN IG SIH MT SOT CT SL A 50 00 30 00 30 00 3 R N -1 2 -

3rw slce. os eetd

Como se puede ver, FORD desaparecio de los resultados. De todas formas, puede ocurrir que si se ejecuta este mismo update en otra maquina, FORD no desaparezca sino que sea SCOTT o SMITH. La columna que va a desaparecer es aleatoria, lo decide el motor segun la manera en la cual tenga ordenado internamente los datos. Esto muestra el problema con los queries top-n en general: Si se esta ordenando por algo no unico, el primer set de n filas que se obtiene puede ser diferente, dados los mismos datos de entrada. Por ejemplo:

SL cet tbet Q> rae al 2 3 ( nme, x ubr ynme ubr

4 ) ; Tbecetd al rae. SL isr it t Q> net no 2 vle (,0) aus 110; www.epidataconsulting.com/tikiwiki/tiki-read_article.php?articleId=64
3/10

25/06/12

: Utilizando funciones analiticas en Oracle para paginar 2 vle (,0) aus 110;

SL isr it t Q> net no 2 vle (,0) aus 120; SL isr it t Q> net no 2 vle (,0) aus 130; SL isr it t Q> net no i 2 vle (,0) aus 140; SL slc * Q> eet 2 fo rm 3 (eetxy slc ,, 4 5 rwnme( o_ubr) oe (re b x r vr odr y ) n

6 fo t rm ) 7 weer < 3 hr n = ; X 1 1 1 Y 10 0 20 0 30 0 R N 1 2 3

3rw slce. os eetd

Ahora veremos lo que ocurre si vuelvo a cargar la misma tabla con los mismos datos, pero en un orden diferente.

SL tuct tbet Q> rnae al ; Tbetuctd al rnae. SL isr it t Q> net no 2 vle (,0) aus 140; SL isr it t Q> net no 2 vle (,0) aus 120; SL isr it t Q> net no 2 vle (,0) aus 130; SL isr it t Q> net no 2 vle (,0) aus 110; SL slc * Q> eet 2 fo rm 3 (eetxy slc ,, 4 5 rwnme( o_ubr) oe(re b xy r vrodr y ,) n

6 fo t rm ) 7 weer < 3 hr n = ; X 1 1 1 Y 40 0 20 0 30 0 R N -1 2 3

3rw slce. os eetd


www.epidataconsulting.com/tikiwiki/tiki-read_article.php?articleId=64 4/10

25/06/12

: Utilizando funciones analiticas en Oracle para paginar

Como podemos ver, obtuvimos una respuesta totalmente diferente. Esto es algo que se tiene que tener en cuenta cuando se ejecuta un query del tipo top-n y se esta ordenando por un atributo que no es unico. Teniendo lo anterior en cuenta, se puede utilizar otra funcion analitica para eliminar esta ambigedad. Si bien la funcion eliminara dicha ambigedad, para hacerlo devolvera mas de n filas. Cuando se ordena por un atributo que no es unico, es posible que se quieran obtener todos los registros relevantes - no solamente los primeros n registros aleatorios. Para lograr esto, usaremos las funciones analiticas RANK y DENSE_RANK:

SL slc eaesl Q> eet nm,a, 2 3 4 5 6 7 8 9 1 / 0 EAE NM -----------KN IG FR OD SOT CT JNS OE BAE LK CAK LR . . . 1 rw slce. 4 os eetd SL A ----50 00 30 00 30 00 27 95 25 80 25 40 3 4 5 6 R N ---1 2 2 4 5 6 RK N -----1 2 2 3 4 5 DN RK --------1 2 rwnme( o_ubr) oe (re b slds)r, vr odr y a ec n rn( ak) oe (re b slds rk vr odr y a e) n, dnern( es_ak) oe (re b slds)rk vr odr y a ecdn fo ep rm m odrb slds re y a ec

Lo que deberiamos notar aqui seria: ROW_NUMBER asigna numeros contiguos y unicos desde 1..N a todo el resultset. RANK no asigna numeros unicos - FORD y SCOTT estan empatados en el segundo puesto- y tampoco asigna numeros contiguos. Ningun registro tuvo el numero 3, debido a que dos personas estan empatadas en el segundo puesto. DENSE_RANK, al igual que RANK, no asigna numeros unicos, pero si asigna numeros contiguos. Mas alla de que dos registros esten empatados en el segundo lugar, existe un registro que tiene el tercer puesto. Se puede usar RANK y DENSE_RANK de la misma manera que se usaria ROW_NUMBER para restringir el numero de filas obtenidas, pero obviamente se obtendran resultados diferentes, por ejemplo:

www.epidataconsulting.com/tikiwiki/tiki-read_article.php?articleId=64

5/10

25/06/12

: Utilizando funciones analiticas en Oracle para paginar

SL slc * Q> eet 2 fo ( rm 3 slc eae sl eet nm, a, 4 5 dnern( es_ak) oe (re b slds)dn vr odr y a ec rk

6 fo ep rm m 7 )weedn < 3 hr rk = 8 odrb slds re y a ec 9/ EAE NM -----------KN IG SOT CT FR OD JNS OE 4rw slce. os eetd SL A ---50 00 30 00 30 00 27 95 2 2 3 DN RK -------1

Este query devuelve "el grupo de personas que tienen los mejores 3 salarios", que es lo que nosotros buscamos. Obtener los tres primeros registros de EMP luego de ordenar por SAL es arbitrario debido a que usando el mismo set de datos,insertados en distinto orden, genera resultados diferentes usando ROW_NUMBER (debido a que SAL no es unico). Usando DENSE_RANK, no obtenemos precisamente tres registros, pero obtenemos un resultado repetible y deterministico. Top-N query agrupado por algo Usar funciones analiticas es mucho mejor que utilizar la pseudocolumna ROWNUM cuando se intentan procesar queries mas complejos. Por ejemplo, supongamos que se desea obtener los top-n empleados mejores pagos de la tabla EMP segun el DEPTNO. Esto es, para cada departamento, mostrar los tres empleados mejores pagos (o el conjunto de personas que conforman los tres mejores salarios utilizando DENSE_RANK). Para lograr esto, necesitamos "partir" el resultado por DEPTNO, ordenarlo por SAL DESC, y luego asignar el resultado de la funcion analitica a cada fila. Afortunadamente, las funciones analiticas estan diseadas para hacer exactamente este tipo de trabajo. Por ejemplo:

SL beko dpn si 1 Q> ra n eto kp SL slc dpn,eae sl Q> eet eto nm, a, 2 3 4 5 6 7 8 9 1 0 1 1 1 2 fo ep rm m odrb dpn,slds re y eto a ec
6/10

rwnme( o_ubr) oe (atto b dpn vr priin y eto odrb slds)n re y a ecr, rn( ak) oe (atto b dpn vr priin y eto odrb slds)n, re y a ecrk dnern( es_ak) oe (atto b dpn vr priin y eto odrb slds)rk re y a ecdn

www.epidataconsulting.com/tikiwiki/tiki-read_article.php?articleId=64

25/06/12

: Utilizando funciones analiticas en Oracle para paginar

1 / 3 DPN ETO -----1 0 EAE NM -----KN IG CAK LR MLE ILR 2 0 SOT CT FR OD JNS OE AAS DM SIH MT 3 0 BAE LK ALN LE TRE UNR MRI ATN WR AD JMS AE 1 rw slce. 4 os eetd SL A --50 00 25 40 10 30 30 00 30 00 27 95 10 10 80 0 25 80 10 60 10 50 15 20 15 20 90 5 1 2 3 4 5 1 2 3 4 5 6 R N RK N 1 2 3 1 1 3 4 5 1 2 3 4 4 6 -1 2 3 1 1 2 3 4 1 2 3 4 4 5 DN RK ---1 2 3

Aqui utilizamos la clausula PARTITION, la cual parte el resultado en un numero determinado de grupos y luego aplica las funciones analiticas a cada grupo, reseteando el contador a medida que pasa de grupo a grupo. Esto nos permite asignar un numero incremental -utilizando ROW_NUMBER, por ejemplo- a las filas de cada departamento, reseteando ROW_NUMBER a 1 a medida que cambio de grupo. Como sep uede ver, es sencillo obtener "los primero 3 por departamento", utilizando una vista inline y aplicando el predicado WHERE RN <=3 o RNK <= 3 o DRNK <= 3, dependiendo de que metodo de numeracion utilicemos. Entonces, por ejemplo, para obtener el conjunto de los empleados que tienen los tres mejores salarios de cada departamente, utilizaria el siguiente query:

SL beko dpn si 1 Q> ra n eto kp SL slc * Q> eet 2 3 4 5 6 7 8 9 1 / 0 DPN ETO -----1 0
www.epidataconsulting.com/tikiwiki/tiki-read_article.php?articleId=64

fo ( rm slc dpn,eae sl eet eto nm, a, dnern( es_ak) oe (atto b dpn vr priin y eto odrb slds)dn re y a ec rk fo ep rm m )weedn < 3 hr rk = odrb dpn,slds re y eto a ec

EAE NM KN IG

SL A -----

DN RK -50 00 25 40 ---1 2
7/10

CAK LR

25/06/12

: Utilizando funciones analiticas en Oracle para paginar CAK LR 25 40

2 3 1 1 2 3 1 2 3

MLE ILR 2 0 SOT CT FR OD JNS OE AAS DM 3 0 BAE LK ALN LE TRE UNR 1 rw slce. 0 os eetd

10 30 30 00 30 00 27 95 10 10 25 80 10 60 10 50

Paginacion obteniendo las filas desde la N hasta la M La paginacion es comun en las aplicaciones Web: El usuario ingresa un cierto criterio de busqueda, que ejecuta un query y luego se le permite al usuario clickear en "anterior" y "siguiente" para navegar entre las distintas paginas. Para lograr esta funcionalidad, la aplicacion necesita poder obtener un cierto conjunto de filas de un query. En el articulo anterior, que se hablaba de ROWNUN, y en la seccion anterior, vimos como lograr esta paginacion, pero requiere dos niveles de vistas inline y puede ser considerado "complicado". Una manera sintacticamente mas facil de escribir el query de paginacion es:

slc * eet fo ( rm slc /+is_os2)* eet *frtrw(5 / <ouns clma> rwnme( o_ubr) oe (re b <louio)n vr odr y ag nc>r fo <als) rm tba> weer bten: ad: hr n ewe n n m odrb r; re y n

Por ejemplo, supongamos que deseamos paginar la vista ALL_OBJECT, queremos mostrar de a 25 registros por pagina, y necesitamos mostrar la pagina 5. El query deberia ser:

SL vral nnme Q> aibe ubr SL vral mnme Q> aibe ubr SL ee : : 11 : : 15 Q> xc n = 0; m = 2 P/Q poeuescesul cmltd LSL rcdr ucsfly opee. SL slc * Q> eet 2 3 4 5 6 fo ( rm slc /+frtrw2)* eet * is_o(5 / ojc_d ojc_ae beti, betnm, rwnme( oe o_ubr) vr (re b ojc_d r odr y beti) n
8/10

7 fo alojc) rm l_bet www.epidataconsulting.com/tikiwiki/tiki-read_article.php?articleId=64

25/06/12

: Utilizando funciones analiticas en Oracle para paginar 7 fo alojc) rm l_bet

8 9

weer bten: ad: hr n ewe n n m odrb r; re y n OJC_AE BETNM 12 0 13 0 . . . 14 2 15 2 16 2 IACS1 _CES ITIGR _RGE1 ITIGR _RGE2 13 2 14 2 15 2 ISQ _E1 IOJUH _BAT1 R N -11 0 12 0

OJC_D BETI ---------

----------------

2 rw slce 5 os eetd

Utilizamos 25 en la /*+ first_row */ debido a que es nuestro tamao de pagina y que estos tipos de queries deben ser optimizados para obtener la primera pagina tan pronto como sea posible. Asignamos ROW_NUMBER a cada fila luego de ordenar por OBJECT_ID. Luego, utilizamos un simple BETWEEN para obtener las filas que necesitamos (101 hasta 125 en este caso). Es necesario ordenar por algo unico en estos queries de paginacion, para que ROW_NUMBER sea asignado deterministicamente a las filas. Caso contrario, terminariamos con un problema similar al mencionado anteriormente cuando nos referiamos a los salarios. El GROUP BY ordena? La clausula GROUP BY en un query garantiza que los datos de salida seran ordenados segun la columna GROUP BY, mas alla de que no exista una clausula ORDER BY? Salvo que exista una clausula ORDER BY en un query, no se puede asegurar que las filas devueltas por un query vuelvan ordenadas. Sin ORDER BY, los datos pueden ser devueltos en cualquier orden en el cual la base de datos desee. De hecho, en la base Oracle Database 10g Release 2, los datos devueltos por GROUP BY vuelven mas aleatorios que nunca:

SL stattaeo epan Q> e uorc n xli SL slc jb cut* Q> eet o, on() 2 3 4/ JB O ------CEK LR SLSA AEMN PEIET RSDN MNGR AAE AAYT NLS 4 1 3 2 CUT* ON() --------4 fo ep rm m gopb jb ru y o

-----------------------------------------------|I d |Oeain prto |Nm ae |


9/10

-----------------------------------------------www.epidataconsulting.com/tikiwiki/tiki-read_article.php?articleId=64

25/06/12

: Utilizando funciones analiticas en Oracle para paginar ------------------------------------------------

|0 |1 |2

|SLC SAEET EET TTMN | HS GOPB AH RU Y | TBEACS FL AL CES UL

| | |EP M |

| |

------------------------------------------------

El paso HASH GROUP BY en el explain plan es un nuevo y mas eficiente query plan para las operaciones GROUP BY y definitivamente no ordena datos. Solo utilizando ORDER BY se puede asumir el orden de los datos.

Epidata Consulting | Base de conocimiento

Wiki

Artculos

Foros

| Tema: Tikinewt

www.epidataconsulting.com/tikiwiki/tiki-read_article.php?articleId=64

10/10

Vous aimerez peut-être aussi