144 votes

Décalage de rangée dans SQL Server

Existe-t-il un moyen dans SQL Server d'obtenir les résultats à partir d'un décalage donné ? Par exemple, dans un autre type de base de données SQL, il est possible de faire :

SELECT * FROM MyTable OFFSET 50 LIMIT 25

pour obtenir les résultats 51-75. Cette construction ne semble pas exister dans le serveur SQL.

Comment puis-je accomplir cela sans charger toutes les lignes dont je ne me soucie pas ? Merci !

0 votes

Vous pouvez utiliser les instructions offset et fetch next. youtu.be/EqHkAiiBwPc

0 votes

Pour les personnes qui préfèrent les documents officiels aux vidéos : learn.microsoft.com/fr/sql/t-sql/queries/

160voto

Brian Kim Points 8951

J'éviterais d'utiliser SELECT * . Indiquez les colonnes que vous souhaitez réellement, même si elles sont toutes présentes.

Serveur SQL 2005+.

SELECT col1, col2 
FROM (
    SELECT col1, col2, ROW_NUMBER() OVER (ORDER BY ID) AS RowNum
    FROM MyTable
) AS MyDerivedTable
WHERE MyDerivedTable.RowNum BETWEEN @startRow AND @endRow

SQL Server 2000

Pagination efficace dans les grands ensembles de résultats en SQL Server 2000

Une méthode plus efficace pour paginer dans de grands ensembles de résultats

6 votes

Pourquoi suggérez-vous d'éviter le SELECT même si vous sélectionnez toutes les colonnes ?

15 votes

Je suis sûr qu'il a utilisé "*" parce que c'était plus simple à taper et que cela faisait mieux passer le message que "col1, col2, ... colN".

9 votes

Quant à savoir pourquoi ne pas l'utiliser, SELECT * signifie que si la structure de la table change, votre requête s'exécute toujours, mais donne des résultats différents. Si une colonne est ajoutée, cela peut être utile (bien que vous deviez toujours l'utiliser par son nom quelque part) ; si une colonne est supprimée ou renommée, il vaut mieux que votre SQL se casse visiblement que le code situé plus bas se comporte bizarrement parce qu'une variable n'est pas initialisée.

112voto

Martin Smith Points 174101

Si vous traitez toutes les pages dans l'ordre, il suffit de se souvenir de la dernière valeur de clé vue sur la page précédente et d'utiliser TOP (25) ... WHERE Key > @last_key ORDER BY Key peut être la méthode la plus performante si des index appropriés existent pour permettre une recherche efficace - ou bien un curseur API s'ils ne le font pas.

Pour la sélection d'une page arbitraire, la meilleure solution pour SQL Server 2005 - 2008 R2 est probablement ROW_NUMBER y BETWEEN

Pour SQL Server 2012+, vous pouvez utiliser la version améliorée de l'interface utilisateur. ORDER BY pour ce besoin.

SELECT  *
FROM     MyTable 
ORDER BY OrderingColumn ASC 
OFFSET  50 ROWS 
FETCH NEXT 25 ROWS ONLY 

Bien que il reste à voir dans quelle mesure cette option sera performante .

2 votes

Il est maintenant disponible dans SQL Server Compact 4.0 --> msdn.microsoft.com/fr/us/library/gg699618(v=sql.110).aspx

13 votes

Il est temps qu'ils ajoutent ceci à TSQL.

3 votes

Seulement pour Sql Server 2012 :(

23voto

leoinfo Points 3364

Voici une façon de procéder (SQL2000)

SELECT * FROM
(
    SELECT TOP (@pageSize) * FROM
    (
        SELECT TOP (@pageNumber * @pageSize) *
        FROM tableName 
        ORDER BY columnName ASC
    ) AS t1 
    ORDER BY columnName DESC
) AS t2 
ORDER BY columnName ASC

et voici une autre façon (SQL 2005)

;WITH results AS (
    SELECT 
        rowNo = ROW_NUMBER() OVER( ORDER BY columnName ASC )
        , *
    FROM tableName 
) 
SELECT * 
FROM results
WHERE rowNo between (@pageNumber-1)*@pageSize+1 and @pageNumber*@pageSize

0 votes

Juste pour clarifier le premier point... (@pageSize) est un paramètre de remplacement pour la valeur réelle. Vous devrez faire le 'TOP 25' spécifiquement ; SQL Server 2000 ne supporte pas les variables dans une clause TOP. Cela rend difficile l'utilisation de SQL dynamique.

5 votes

Cette solution pour SQL2000 ne fonctionne pas pour la dernière page du jeu de résultats, sauf si le nombre total de lignes est un multiple de la taille de la page.

11voto

Matthias Meid Points 8473

Vous pouvez utiliser ROW_NUMBER() pour obtenir ce que vous voulez :

SELECT *
FROM (SELECT ROW_NUMBER() OVER(ORDER BY id) RowNr, id FROM tbl) t
WHERE RowNr BETWEEN 10 AND 20

6voto

Arthur van Dijk Points 51

Pour les tableaux avec des colonnes de données plus nombreuses et plus grandes, je préfère :

SELECT 
  tablename.col1,
  tablename.col2,
  tablename.col3,
  ...
FROM
(
  (
    SELECT
      col1
    FROM 
    (
      SELECT col1, ROW_NUMBER() OVER (ORDER BY col1 ASC) AS RowNum
      FROM tablename
      WHERE ([CONDITION])
    )
    AS T1 WHERE T1.RowNum BETWEEN [OFFSET] AND [OFFSET + LIMIT]
  )
  AS T2 INNER JOIN tablename ON T2.col1=tablename.col1
);

-

[CONDITION] can contain any WHERE clause for searching.
[OFFSET] specifies the start,
[LIMIT] the maximum results.

Ses performances sont bien meilleures sur les tables contenant des données volumineuses, comme les BLOB, car la fonction ROW_NUMBER ne doit examiner qu'une seule colonne et seules les lignes correspondantes sont renvoyées avec toutes les colonnes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X