web-dev-qa-db-fra.com

Sélectionnez les rangées supérieure et inférieure

J'utilise SQL Server 2005 et j'essaie de réaliser quelque chose comme ceci: Je veux obtenir les x premières lignes et les x dernières lignes dans la même instruction select.

SELECT TOP(5) BOTTOM(5)

Bien entendu, BOTTOM n'existe pas, j'ai donc besoin d'une autre solution. Je crois qu'il existe une solution simple et élégante que je ne comprends pas. Refaire la sélection avec GROUP BY DESC n'est pas une option.

12
Adrian Fâciu

Utiliser un syndicat est la seule chose à laquelle je peux penser pour accomplir cela.

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
22
Ralf de Kleine

Vérifiez le lien

SQL SERVER - Comment récupérer des lignes TOP et BOTTOM ensemble à l’aide de T-SQL

Avez-vous essayé d'utiliser le nombre de retour?

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

8
hgulyan

Je pense que vous avez deux options principales:

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

UNION

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

Ou, si vous savez combien d'éléments il y a dans le tableau:

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
7
Paul

Est-ce une option pour vous d'utiliser un syndicat?

Par exemple. 

select top 5 ... order by {specify columns asc} 
union 
select top 5 ... order by {specify columns desc}
3
Chris W

Aucune différence réelle entre cela et le syndicat que je sache, mais techniquement, il s'agit d'une requête unique.

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);
2
Sako73

Ensuite, vous êtes parti - faites à nouveau la sélection IS la seule option, à moins que vous ne vouliez extraire le jeu de résultats complet puis tout jeter entre les deux.

N'importe quel sql que je pense est la même chose - pour le fond, vous devez d'abord savoir combien d'articles vous avez (tout matérialiser ou utiliser count (*)) ou un ordre de tri inversé.

Désolé si cela ne vous convient pas, mais à la fin ... la réalité s'en fiche, et je ne vois pas d'autre moyen de le faire.

1
TomTom

je suppose que vous devez le faire en utilisant uniquement la sous-requête

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) 
  )

ÉDITÉ

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

Je devais le faire récemment pour une très grande procédure stockée; Si votre requête est assez volumineuse et que vous souhaitez minimiser le nombre de requêtes, vous pouvez déclarer un @tempTable, insérer dans ce @tempTable puis interroger à partir de ce @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
0
Ernest