¿Puede decirnos el orden según el cual desea 'top 1'?
Andrew Wolfe
1
En primer lugar, nunca debe confiar en el motor DB para hacer eso. Si quieres saber cosas así, pon un secuenciador. Cuando lo haga, se garantiza que se numerarán en el orden en que se insertaron.
Esto es bueno si solo quieres 1 fila y no te importa cuál. Si desea filas específicas, como el registro más reciente, debe ordenarlas en una subselección, como la respuesta de Vash. Oracle asigna rownums antes del género.
Scott Bailey
44
@Scott sí. eso es correcto. Y Patrick, buen punto, creo que la sintaxis es incorrecta en eso. Realmente debería ser un aplazamiento (dense_rank () último ...)
mcpeterson
2
La diferencia entre el primer y el segundo ejemplo es que el primero selecciona una fila A (cualquier fila, sin orden). El segundo ejemplo obtiene el valor de la primera fila, sin hacer una consulta interna de orden (como en los ejemplos a continuación).
JulesLt
3
La sintaxis no es correcta en: seleccione max (fname) over (rank () ordenado por some_factor) de MyTbl
Stéphane Gerber el
1
@jclozano "no es una funcionalidad muy conocida de Oracle" - Con respeto, ruego diferir. Esto es importante porque la "funcionalidad no conocida" tiende a implicar oscuridad y, por lo tanto, podría sugerir que debemos evitar el uso. Esto no es oscuro, y no debe evitarse su uso.
Comando interesante, estoy usando 12c aquí y OFFSET 0 ROWSaparentemente no es necesario, puedes usar FETCH NEXT 1 ROWS ONLYo incluso FETCH FIRST ROW ONLY, el orden por es importante o será equivalente a solo usar a WHERE rownum = 1. Incluso lo probé en una instrucción APLICACIÓN EXTERIOR y funcionó como la función TOP de Ms-SQL allí.
Rafael Merlin
Tienes razón @RafaelMerlin. Después de su publicación, reconocí que OFFSET 0 ROWS no es necesario. Sería útil al recuperar datos entre la parte superior X y la parte superior Y.
Hasta ahora todo bien, con un importante punto que falta TIES. Consulte esto para los casos en que se producen corbatas para la versión 12c +y12c -
Barbaros Özhan
10
Puede usar ROW_NUMBER()una ORDER BYcláusula en subconsulta y usar esta columna en reemplazo deTOP N . Esto se puede explicar paso a paso.
Vea la tabla a continuación que tiene dos columnas NAMEy DT_CREATED.
Si necesita tomar solo las dos primeras fechas independientemente de NAME, puede usar la consulta a continuación. La lógica ha sido escrita dentro de la consulta
-- The number of records can be specified in WHERE clauseSELECT RNO,NAME,DT_CREATED
FROM(-- Generates numbers in a column in sequence in the order of dateSELECT ROW_NUMBER()OVER(ORDERBY DT_CREATED)AS RNO,
NAME,DT_CREATED
FROM DEMOTOP
)TAB
WHERE RNO<3;
RESULTADO
En algunas situaciones, necesitamos seleccionar TOP Nresultados respectivos a cada uno NAME. En tal caso, podemos usar PARTITION BYcon una ORDER BYcláusula en subconsulta. Consulte la consulta a continuación.
-- The number of records can be specified in WHERE clauseSELECT RNO,NAME,DT_CREATED
FROM(--Generates numbers in a column in sequence in the order of date for each NAMESELECT ROW_NUMBER()OVER(PARTITIONBY NAME ORDERBY DT_CREATED)AS RNO,
NAME,DT_CREATED
FROM DEMOTOP
)TAB
WHERE RNO<3;
Usar ROW_NUMBER () ... es una solución más correcta que en la respuesta al tema. Un problema con esta solución (y con la variante max (field) también) es que no puede hacer cosas como "seleccionar ... (seleccione ROW_NUMBER () ...) para actualizar ";
Alexo Po.
Y a veces es muy importante en PL / SQL (lo siento, no se pudo editar el comentario anterior en el límite de 5 minutos).
Alexo Po.
En tal caso, podemos usar CTE como en la parte exterior. ¿Correcto? @Alexo Po.
Sarath Avanavu
Creo que no te entiendo. para la cláusula de actualización se puede utilizar cuando Oracle preserva "ROWID" fácilmente. Por lo tanto, la agrupación (y la agrupación debido al uso de la cláusula analítica) oculta el ROWID real y las filas no se pueden bloquear. Y segundo, CTE ( with (select ... ) as cláusula) no cambia nada a este problema, CTE solo tiene como objetivo leer y respaldar consultas. ¿Correcto? @Sarath Avanavu
Alexo Po.
Nota sobre mi mismo. El problema con ROWID en realidad ocurre específicamente porque la condición RNO <3 , en este caso, el valor de RNO no está conectado con ROWID, por lo que Oracle no puede bloquear filas.
Alexo Po.
9
Puedes hacer algo como
SELECT*FROM(SELECT Fname FROM MyTbl ORDERBY Fname )WHERE rownum =1;
También puedes usar las funciones analíticas RANK y / o DENSE_RANK , pero ROWNUM es probablemente la más fácil.
@carpenteri: Es cierto, los análisis estaban disponibles en 8i, no puedo recordar los detalles, pero los análisis no estaban realmente disponibles para el público hasta el 9i.
OMG Ponis
Pequeño comentario: la respuesta de Vash a continuación incluye un ORDER BY en la consulta interna que es fundamental si desea el valor TOP de fname, en lugar de 'first' (que puede ser cualquier cosa, probablemente la primera fila insertada). ¿Podría valer la pena una edición?
JulesLt
@JulesLt: la consulta proporcionada por el OP no incluye un ORDER BY, por lo que esta es la respuesta representa y la traducción exacta a la sintaxis de Oracle.
OMG Ponis
Mi malentendido de la sintaxis de SQL SERVER TOP (supuse erróneamente que era similar a FIRST in RANK, no ROWNUM). Votado
JulesLt
3
Seleccionar la primera fila de una tabla y seleccionar una fila de una tabla son dos tareas diferentes y necesitan una consulta diferente. Hay muchas formas posibles de hacerlo. Cuatro de ellos son:
primero
select max(Fname)from MyTbl;
Segundo
select min(Fname)from MyTbl;
Tercero
select Fname from MyTbl where rownum =1;
Cuarto
select max(Fname)from MyTbl where rowid=(select max(rowid)from MyTbl)
Respuestas:
Si solo desea una primera fila seleccionada, puede:
También puede usar funciones analíticas para ordenar y tomar la x superior:
fuente
fuente
top X
ejemplo, puede cambiarlo aWHERE ROWNUM <= X
Con Oracle 12c (junio de 2013), puede usarlo de la siguiente manera.
fuente
OFFSET 0 ROWS
aparentemente no es necesario, puedes usarFETCH NEXT 1 ROWS ONLY
o inclusoFETCH FIRST ROW ONLY
, el orden por es importante o será equivalente a solo usar aWHERE rownum = 1
. Incluso lo probé en una instrucción APLICACIÓN EXTERIOR y funcionó como la función TOP de Ms-SQL allí.TIES
. Consulte esto para los casos en que se producen corbatas para la versión12c +
y12c -
Puede usar
ROW_NUMBER()
unaORDER BY
cláusula en subconsulta y usar esta columna en reemplazo deTOP N
. Esto se puede explicar paso a paso.Vea la tabla a continuación que tiene dos columnas
NAME
yDT_CREATED
.Si necesita tomar solo las dos primeras fechas independientemente de
NAME
, puede usar la consulta a continuación. La lógica ha sido escrita dentro de la consultaRESULTADO
En algunas situaciones, necesitamos seleccionar
TOP N
resultados respectivos a cada unoNAME
. En tal caso, podemos usarPARTITION BY
con unaORDER BY
cláusula en subconsulta. Consulte la consulta a continuación.RESULTADO
fuente
with (select ... ) as
cláusula) no cambia nada a este problema, CTE solo tiene como objetivo leer y respaldar consultas. ¿Correcto? @Sarath AvanavuPuedes hacer algo como
También puedes usar las funciones analíticas RANK y / o DENSE_RANK , pero ROWNUM es probablemente la más fácil.
fuente
fuente
Utilizar:
Si usa Oracle9i +, podría usar funciones analíticas como ROW_NUMBER () pero no funcionarán tan bien como ROWNUM .
fuente
Seleccionar la primera fila de una tabla y seleccionar una fila de una tabla son dos tareas diferentes y necesitan una consulta diferente. Hay muchas formas posibles de hacerlo. Cuatro de ellos son:
primero
Segundo
Tercero
Cuarto
fuente
Tuve el mismo problema y puedo solucionarlo con esta solución:
Puede ordenar su resultado antes para tener el primer valor en la parte superior.
Buena suerte
fuente