Respuestas:
SELECT
columns
FROM
(
SELECT TOP 200
columns
FROM
My_Table
ORDER BY
a_column DESC
) SQ
ORDER BY
a_column ASC
Es innecesario. Puede usar ORDER BY
y simplemente cambiar el orden a DESC
para obtener el mismo efecto.
Lo siento, pero no creo que vea ninguna respuesta correcta en mi opinión.
La TOP
función x muestra los registros en orden indefinido. De esa definición se deduce que una BOTTOM
función no se puede definir.
Independiente de cualquier índice u orden de clasificación. Cuando haces una ORDER BY y DESC
, obtienes primero las filas con el valor de y más alto. Si se trata de una identificación generada automáticamente, debería mostrar los registros que se agregaron por última vez a la tabla, como se sugiere en las otras respuestas. Sin embargo:
TOP
funciónLa respuesta correcta debería ser que no hay, y no puede haber, un equivalente a TOP
para obtener las filas inferiores.
Lógicamente
BOTTOM (x) is all the records except TOP (n - x), where n is the count; x <= n
Por ejemplo, seleccione los 1000 inferiores de Empleado:
En T-SQL,
DECLARE
@bottom int,
@count int
SET @bottom = 1000
SET @count = (select COUNT(*) from Employee)
select * from Employee emp where emp.EmployeeID not in
(
SELECT TOP (@count-@bottom) Employee.EmployeeID FROM Employee
)
Parecería que a cualquiera de las respuestas que implementan una cláusula ORDER BY en la solución le falta el punto o no entiende realmente lo que TOP le devuelve.
TOP devuelve un conjunto de resultados de consulta desordenado que limita el conjunto de registros a los primeros N registros devueltos. (Desde una perspectiva de Oracle, es similar a agregar un donde ROWNUM <(N + 1).
Cualquier solución que use un orden, puede devolver filas que también son devueltas por la cláusula TOP (ya que ese conjunto de datos estaba desordenado en primer lugar), dependiendo de qué criterio se usó en el pedido por
La utilidad de TOP es que una vez que el conjunto de datos alcanza un cierto tamaño N, deja de buscar filas. Puede tener una idea de cómo se ven los datos sin tener que buscarlos todos.
Para implementar BOTTOM con precisión, necesitaría buscar todo el conjunto de datos desordenado y luego restringir el conjunto de datos a los N registros finales. Eso no será particularmente efectivo si se trata de mesas enormes. Tampoco necesariamente le dará lo que cree que está pidiendo. El final del conjunto de datos puede no ser necesariamente "las últimas filas insertadas" (y probablemente no lo será para la mayoría de las aplicaciones intensivas de DML).
De manera similar, las soluciones que implementan un ORDER BY son, desafortunadamente, potencialmente desastrosas cuando se trata de grandes conjuntos de datos. Si tengo, digamos, 10 mil millones de registros y quiero los últimos 10, es una tontería pedir 10 mil millones de registros y seleccionar los últimos 10.
El problema aquí es que BOTTOM no tiene el significado que pensamos cuando lo comparamos con TOP.
Cuando los registros se insertan, eliminan, insertan, eliminan una y otra y otra vez, aparecerán algunos espacios en el almacenamiento y, más tarde, se colocarán filas, si es posible. Pero lo que vemos a menudo, cuando seleccionamos TOP, parecen ser datos ordenados, porque es posible que se hayan insertado al principio de la existencia de la tabla. Si la tabla no experimenta muchas eliminaciones, puede aparecer que está ordenada. (por ejemplo, las fechas de creación pueden ser tan antiguas como la propia creación de la tabla). Pero la realidad es que, si se trata de una tabla con muchas eliminaciones, es posible que las N filas TOP no se parezcan a eso en absoluto.
Entonces, la conclusión aquí (juego de palabras) es que alguien que está pidiendo los registros de BOTTOM N no sabe realmente lo que está pidiendo. O, al menos, lo que están pidiendo y lo que realmente significa BOTTOM no son lo mismo.
Entonces, la solución puede satisfacer la necesidad comercial real del solicitante ... pero no cumple con los criterios para ser la PARTE INFERIOR.
insert
declaración grande para poner filas en una tabla grande sin indexar. (Primero estoy llenando la tabla antes de comenzar a indexarla). Perdí mi sesión de cliente debido a un reinicio o lo que sea, y ahora quiero ver si mis filas recién agregadas están allí. Si la fila 'inferior' de la tabla es una de mis últimas, sé que la operación se completó. Si la fila 'inferior' es otra cosa, bueno, no hay garantías y tengo que escanear toda la tabla para asegurarme ... pero lo más probable es que pueda ahorrar algo de tiempo comprobando rápidamente la 'inferior' al igual que usted puede ' parte superior'.
La respuesta actualmente aceptada por "Justin Ethier" no es una respuesta correcta como lo señaló "Protector uno".
Por lo que puedo ver, hasta ahora, ninguna otra respuesta o comentario proporciona el equivalente de BOTTOM (x) que pidió el autor de la pregunta.
Primero, consideremos un escenario en el que se necesitaría esta funcionalidad:
SELECT * FROM Split('apple,orange,banana,apple,lime',',')
Esto devuelve una tabla de una columna y cinco registros:
Como puede ver: no tenemos una columna de ID; no podemos ordenar por la columna devuelta; y no podemos seleccionar los dos registros inferiores usando SQL estándar como podemos hacer para los dos registros superiores.
Aquí está mi intento de proporcionar una solución:
SELECT * INTO #mytemptable FROM Split('apple,orange,banana,apple,lime',',')
ALTER TABLE #mytemptable ADD tempID INT IDENTITY
SELECT TOP 2 * FROM #mytemptable ORDER BY tempID DESC
DROP TABLE #mytemptable
Y aquí hay una solución más completa:
SELECT * INTO #mytemptable FROM Split('apple,orange,banana,apple,lime',',')
ALTER TABLE #mytemptable ADD tempID INT IDENTITY
DELETE FROM #mytemptable WHERE tempID <= ((SELECT COUNT(*) FROM #mytemptable) - 2)
ALTER TABLE #mytemptable DROP COLUMN tempID
SELECT * FROM #mytemptable
DROP TABLE #mytemptable
De ninguna manera estoy afirmando que esta sea una buena idea para usar en todas las circunstancias, pero proporciona los resultados deseados.
Todo lo que necesita hacer es invertir su ORDER BY
. Agréguelo o elimínelo DESC
.
El problema de ordenar al revés es que a menudo no hace un buen uso de los índices. Tampoco es muy ampliable si alguna vez necesita seleccionar una cantidad de filas que no están al principio o al final. Una forma alternativa es la siguiente.
DECLARE @NumberOfRows int;
SET @NumberOfRows = (SELECT COUNT(*) FROM TheTable);
SELECT col1, col2,...
FROM (
SELECT col1, col2,..., ROW_NUMBER() OVER (ORDER BY col1) AS intRow
FROM TheTable
) AS T
WHERE intRow > @NumberOfRows - 20;
La respuesta de "Tom H" anterior es correcta y me funciona para obtener las 5 filas inferiores.
SELECT [KeyCol1], [KeyCol2], [Col3]
FROM
(SELECT TOP 5 [KeyCol1],
[KeyCol2],
[Col3]
FROM [dbo].[table_name]
ORDER BY [KeyCol1],[KeyCol2] DESC) SOME_ALAIS
ORDER BY [KeyCol1],[KeyCol2] ASC
Gracias.
prueba esto.
declare @floor int --this is the offset from the bottom, the number of results to exclude
declare @resultLimit int --the number of results actually retrieved for use
declare @total int --just adds them up, the total number of results fetched initially
--following is for gathering top 60 results total, then getting rid of top 50. We only keep the last 10
set @floor = 50
set @resultLimit = 10
set @total = @floor + @resultLimit
declare @tmp0 table(
--table body
)
declare @tmp1 table(
--table body
)
--this line will drop the wanted results from whatever table we're selecting from
insert into @tmp0
select Top @total --what to select (the where, from, etc)
--using floor, insert the part we don't want into the second tmp table
insert into @tmp1
select top @floor * from @tmp0
--using select except, exclude top x results from the query
select * from @tmp0
except
select * from @tmp1
Se me ocurrió una solución para esto que no requiere que sepas el número de filas devueltas.
Por ejemplo, si desea obtener todas las ubicaciones registradas en una tabla, excepto la última 1 (o 2, o 5, o 34)
SELECT *
FROM
(SELECT ROW_NUMBER() OVER (ORDER BY CreatedDate) AS Row, *
FROM Locations
WHERE UserId = 12345) AS SubQuery
WHERE Row > 1 -- or 2, or 5, or 34
SELECT TOP 10*from TABLE1 ORDER BY ID DESC
Donde ID es la clave principal de TABLE1.
Primero, cree un índice en una subconsulta de acuerdo con el orden original de la tabla usando:
ROW_NUMBER () OVER (ORDER BY (SELECT NULL) ) AS RowIndex
Luego, ordena la tabla descendiendo por la RowIndex
columna que has creado en la consulta principal:
ORDER BY RowIndex DESC
Y finalmente úselo TOP
con la cantidad deseada de filas:
SELECT TOP 1 * --(or 2, or 5, or 34)
FROM (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL) ) AS RowIndex, *
FROM MyTable) AS SubQuery
ORDER BY RowIndex DESC