web-dev-qa-db-fra.com

SQL Server SELECT DERNIERES lignes

C'est une question connue mais la meilleure solution que j'ai trouvée est quelque chose comme:

SELECT TOP N *
FROM MyTable
ORDER BY Id DESC

J'ai une table avec beaucoup de lignes. Il n’est pas possible d’utiliser cette requête car elle prend beaucoup de temps. Alors, comment puis-je sélectionner les N dernières lignes sans utiliser ORDER BY?

MODIFIER

Désolé question dupliquée de celui-ci

111
Diego

Vous pouvez le faire en utilisant également la fonction ROW NUMBER BY PARTITION. Un bon exemple peut être trouvé ici :

J'utilise la table Orders de la base de données Northwind ... Maintenant, récupérons les 5 dernières commandes passées par l'employé 5:

SELECT ORDERID, CUSTOMERID, OrderDate
FROM
(
    SELECT ROW_NUMBER() OVER (PARTITION BY EmployeeID ORDER BY OrderDate DESC) AS OrderedDate,*
    FROM Orders
) as ordlist

WHERE ordlist.EmployeeID = 5
AND ordlist.OrderedDate <= 5
33
JonVD

Vous pouvez faire en sorte que le serveur SQL sélectionne les N dernières lignes à l'aide de ce SQL:

select * from tbl_name order by id desc limit N;
75
Niru Mukund Shah

J'ai testé le code de JonVD, mais j'ai trouvé qu'il était très lent, 6 secondes.

Ce code a pris des 0.

SELECT TOP(5) ORDERID, CUSTOMERID, OrderDate    
FROM Orders where EmployeeID=5    
Order By OrderDate DESC
42
ABI

Si vous souhaitez sélectionner les derniers nombres de lignes d'une table.

La syntaxe sera comme

 select * from table_name except select top 
 (numbers of rows - how many rows you want)* from table_name

Ces déclarations ne fonctionnent que de différentes manières. Merci les gars.

 select * from Products except select top (77-10) * from Products

de cette façon, vous pouvez obtenir les 10 dernières lignes, mais l'ordre montrera de manière descendante 

select top 10 * from products
 order by productId desc 

 select * from products
 where productid in (select top 10 productID from products)
 order by productID desc

 select * from products where productID not in 
 (select top((select COUNT(*) from products ) -10 )productID from products)
13
Prafulla Sutradhar

"Id" est-il indexé? Sinon, c'est une chose importante à faire (je suppose que c'est déjà indexé).

De plus, avez-vous besoin de renvoyer TOUTES les colonnes? Vous pourrez peut-être obtenir une amélioration substantielle de la vitesse si vous n’avez réellement besoin que d’un sous-ensemble plus petit de colonnes pouvant être entièrement COMPORTEMENT par l’index de la colonne ID - par ex. si vous avez un index NONCLUSTERED sur la colonne Id, sans autres champs inclus dans l'index, il devra alors effectuer une recherche sur l'index clusterisé pour que le reste des colonnes soit renvoyé, ce qui pourrait constituer un lot du coût de la requête. S'il s'agit d'un index CLUSTERED ou d'un index NON CLUSTERED qui inclut tous les autres champs que vous souhaitez renvoyer dans la requête, tout devrait bien se passer.

6
AdaTheDev

De manière très générale et pour supporter SQL Server, voici: 

SELECT TOP(N) *
FROM tbl_name
ORDER BY tbl_id DESC

et pour la performance, ce n’est pas mauvais (moins d’une seconde pour plus de 10 000 enregistrements sur machine serveur)

6
Hakam Fostok

D'abord, vous obtenez le plus grand nombre d'enregistrements de 

 Declare @TableRowsCount Int
 select @TableRowsCount= COUNT(*) from <Your_Table>

Et alors :

Dans SQL Server 2012

SELECT *
FROM  <Your_Table> As L
ORDER BY L.<your Field>
OFFSET <@TableRowsCount-@N> ROWS
FETCH NEXT @N ROWS ONLY;

Dans SQL Server 2008

SELECT *
FROM 
(
SELECT ROW_NUMBER() OVER(ORDER BY ID) AS sequencenumber, *
FROM  <Your_Table>
    Order By <your Field>
) AS TempTable
WHERE sequencenumber > @TableRowsCount-@N 
5
Ardalan Shahgholi
select * from (select top 6 * from vwTable order by Hours desc) T order by Hours
4
fth

Voici quelque chose que vous pouvez essayer sans order by mais je pense que cela nécessite que chaque ligne soit unique. N est le nombre de lignes que vous souhaitez, L est le nombre de lignes de la table.

select * from tbl_name except select top L-N * from tbl_name

Comme indiqué précédemment, les lignes renvoyées sont indéfinies.

EDIT: c'est en fait un chien lent. Sans valeur vraiment.

4
Dzamo Norton

Cette requête renvoie les N dernières lignes dans le bon ordre, mais ses performances sont médiocres.

select *
from (
    select top N *
    from TableName t
    order by t.[Id] desc
) as temp
order by temp.[Id]
2
timberhill

Ce n'est peut-être pas tout à fait adapté à la question, mais…

Clause OFFSET

La clause OFFSET number vous permet de sauter un nombre nombre de lignes puis de renvoyer des lignes après cela. 

Ce lien de documentation est à Postgres; Je ne sais pas si cela s'applique à Sybase/MS SQL Server.

2
Basil Bourque

Une technique que j'utilise pour interroger les lignes LES PLUS RÉCENTES dans de très grands tableaux (100 millions ou plus d'un milliard de lignes) limite la requête à "la lecture" du dernier "N "pourcentage de lignes récentes. Ce sont des applications réelles, par exemple, je le fais pour des données météorologiques récentes non historiques, des recherches récentes dans les fils d'actualités ou des données de points de données de localisation GPS récentes.

Il s'agit d'une amélioration considérable des performances si vous savez avec certitude que vos lignes figurent dans le TOP 5 le plus récent du tableau, par exemple. De telle sorte que même s’il existe des index sur les tableaux, les possibilités sont limitées à 5% seulement des rangées de tableaux comportant plus de 100 millions ou plus d’un milliard de rangées. C'est particulièrement le cas lorsque les anciennes données nécessitent lire le disque physique et pas uniquement les lectures logiques en mémoire.

C'est bien plus efficace que SELECT TOP | Pour cent | LIMIT car il ne sélectionne pas les lignes, mais limite simplement la partie des données à rechercher.

DECLARE @RowIdTableA BIGINT
DECLARE @RowIdTableB BIGINT
DECLARE @TopPercent FLOAT

-- Given that there is an Sequential Identity Column
-- Limit query to only rows in the most recent TOP 5% of rows
SET @TopPercent = .05
SELECT @RowIdTableA = (MAX(TableAId) - (MAX(TableAId) * @TopPercent)) FROM TableA
SELECT @RowIdTableB = (MAX(TableBId) - (MAX(TableBId) * @TopPercent)) FROM TableB

SELECT *
FROM TableA a
INNER JOIN TableB b ON a.KeyId = b.KeyId
WHERE a.Id > @RowIdTableA AND b.Id > @RowIdTableB AND
      a.SomeOtherCriteria = 'Whatever'
0
CodeCowboyOrg

utilisez desc avec orderby à la fin de la requête pour obtenir les dernières valeurs.

0
Sara
DECLARE @MYVAR  NVARCHAR(100)
DECLARE @step  int
SET @step = 0;


DECLARE MYTESTCURSOR CURSOR
DYNAMIC 
FOR
SELECT col FROM [dbo].[table]
OPEN MYTESTCURSOR
FETCH LAST FROM MYTESTCURSOR INTO @MYVAR
print @MYVAR;


WHILE @step < 10
BEGIN   
    FETCH PRIOR FROM MYTESTCURSOR INTO @MYVAR
        print @MYVAR;
        SET @step = @step + 1;
END   
CLOSE MYTESTCURSOR
DEALLOCATE MYTESTCURSOR
0
Slava