2010-05-28 15 views
12

Estoy usando SQL Server 2005 y estoy tratando de lograr algo como esto: Quiero obtener las primeras x filas y las últimas x filas en la misma instrucción de selección.Seleccionar las filas superiores e inferiores

SELECT TOP(5) BOTTOM(5) 

Por supuesto BOTTOM no existe, así que necesito otra solución. Creo que hay una solución fácil y elegante que no obtendré. Hacer la selección de nuevo con GROUP BY DESC no es una opción.

Respuesta

22

El uso de una unión es la única cosa que puedo pensar para lograr esto

select * from (select top(5) * from logins order by USERNAME ASC) a 
union 
select * from (select top(5) * from logins order by USERNAME DESC) b 
+0

También hay una manera de usar rownumber . Y debería derecha arriba 2. – hgulyan

+1

@hgulyan: TOP (x) es el método preferido, funciona con ACTUALIZAR y ELIMINAR, también, y también le permite escribir 'TOP (20%)' o 'TOP (@limit)' y así sucesivamente –

+0

No lo sabía. Gracias por la información. – hgulyan

8

Comprobar el enlace

SQL SERVER – How to Retrieve TOP and BOTTOM Rows Together using T-SQL

¿trató de usar rownumber?

SELECT * 
FROM 
(SELECT *, ROW_NUMBER() OVER (Order BY columnName) as TopFive 
    ,ROW_NUMBER() OVER (Order BY columnName Desc) as BottomFive 
    FROM Table 
) 
WHERE TopFive <=5 or BottomFive <=5 

http://www.sqlservercurry.com/2009/02/select-top-n-and-bottom-n-rows-using.html

+1

este código no funcionará. 'Top5' y' Bottom5' no se pueden referenciar así, se obtiene 'Msg 207, nivel 16, estado 1, línea 4 Nombre de columna no válido 'TopFive' ...' Si coloca 'ROW_NUMBER ...'en el DÓNDE aparece' Msg 4108, nivel 15, estado 1, línea 1, las funciones con ventana solo pueden aparecer en las cláusulas SELECT u ORDER BY. Debe ajustar SELECT y FROM en una tabla derivada y extraer el WHERE al consulta externa para que esto funcione, como [@Paul lo hizo en el segundo método en su respuesta] (http://stackoverflow.com/questions/2927475/sql-server-select-top-and-bottom-rows/2927515#2927515) –

+0

Consulta editada. Fue un gran error. – hgulyan

+1

Esto funcionará como un perro sin patas. Use UNION – gbn

1

Entonces usted está fuera - haciendo el selectivo de nuevo es la única opción, a menos que desee para tirar en el conjunto completo de resultados y luego tirar todo en el medio.

CUALQUIER punto que pueda pensar es de la misma manera; para el final, primero debe saber cuántos elementos tiene (materializar todo o usar conteo (*)) o un orden de clasificación inverso.

Disculpa si no te conviene, pero al final ... la realidad no me importa, y no veo otra forma de hacerlo.

1

supongo que tiene que hacerlo usando subconsulta única

select * from table where id in ( 
      (SELECT id ORDER BY columnName LIMIT 5) OR 
      (SELECT id ORDER BY columnName DESC LIMIT 5) 
) 


select * from table where id in ( 
      (SELECT TOP(5) id ORDER BY columnName) OR 
      (SELECT TOP(5) id ORDER BY columnName DESC) 
) 

editado

select * from table where id in ( 
      (SELECT TOP 5 id ORDER BY columnName) OR 
      (SELECT TOP 5 id ORDER BY columnName DESC) 
) 
+0

Es servidor sql, entonces en lugar de LIMIT, necesita usar TOP – hgulyan

+0

oohhhhhhhhh thanx @hgulyan edito que ayude :) – Salil

+0

Msg 156, nivel 15, estado 1, línea 3 Sintaxis incorrecta cerca de la palabra clave 'ORDER'. –

3

¿Es una opción para ti usar una unión?

E.g.

select top 5 ... order by {specify columns asc} 
union 
select top 5 ... order by {specify columns desc} 
+1

Si publica código, * por favor * resalte las líneas y haga clic en el botón "código" (101 010) en la barra de herramientas del editor. –

7

Creo que has dos opciones principales:

SELECT TOP 5 ... 
FROM ... 
ORDER BY ... ASC 

UNION 

SELECT TOP 5 ... 
FROM ... 
ORDER BY ... DESC 

O, si usted sabe cuántos elementos hay en la tabla:

SELECT ... 
FROM (
    SELECT ..., ROW_NUMBER() OVER (ORDER BY ... ASC) AS intRow 
    FROM ... 
) AS T 
WHERE intRow BETWEEN 1 AND 5 OR intRow BETWEEN @Number - 5 AND @Number 
2

No hay diferencia real entre esto y la unión que conozco, pero técnicamente es una consulta única.

select t.* 
from table t 
where t.id in (select top 5 t2.id from table t2 order by MyColumn) 
    or 
    t.id in (select top 5 t2.id from table t2 order by MyColumn desc); 
0

Tuve que hacer esto recientemente para un procedimiento almacenado muy grande; Si la consulta es bastante grande, y se desea minimizar la cantidad de consultas que podría declarar una @tempTable, insertar en que @tempTable después realizar una consulta a partir de ese @tempTable,

DECLARE @tempTable TABLE (columns..) 
INSERT INTO @tempTable 
VALUES (SELECT.. your query here ..) 

SELECT TOP(5) columns FROM @tempTable ORDER BY column ASC -- returns first to last 
SELECT TOP(5) columns FROM @tempTable ORDER BY column DESC -- returns last to first 
Cuestiones relacionadas