Dans PostgreSQL, il existe les mots Limit
- Offset
clés et qui permettront une pagination très simple des ensembles de résultats.
Quelle est la syntaxe équivalente pour SQL Server?
Dans PostgreSQL, il existe les mots Limit
- Offset
clés et qui permettront une pagination très simple des ensembles de résultats.
Quelle est la syntaxe équivalente pour SQL Server?
Réponses:
L'équivalent de LIMIT
is SET ROWCOUNT
, mais si vous voulez une pagination générique, il est préférable d'écrire une requête comme celle-ci:
;WITH Results_CTE AS
(
SELECT
Col1, Col2, ...,
ROW_NUMBER() OVER (ORDER BY SortCol1, SortCol2, ...) AS RowNum
FROM Table
WHERE <whatever>
)
SELECT *
FROM Results_CTE
WHERE RowNum >= @Offset
AND RowNum < @Offset + @Limit
L'avantage ici est le paramétrage de l'offset et de la limite au cas où vous décideriez de modifier vos options de pagination (ou autoriser l'utilisateur à le faire).
Remarque: le @Offset
paramètre doit utiliser pour cela l'indexation basée sur un plutôt que l'indexation de base zéro normale.
WHERE RowNum >= (@Offset + 1)
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified
. MSSQL2008 R2.
Table
a 200k enregistrements, il va tout d'abord récupérer, puis appliquer la limite? Cette requête est-elle efficace?
Cette fonctionnalité est désormais simplifiée dans SQL Server 2012. Cela fonctionne à partir de SQL Server 2012.
Limiter avec décalage pour sélectionner 11 à 20 lignes dans SQL Server:
SELECT email FROM emailTable
WHERE user_id=3
ORDER BY Id
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
OFFSET
: nombre de lignes ignoréesNEXT
: nombre requis de lignes suivantesSQL_CALC_FOUND_ROWS
lors de son utilisation?
select top {LIMIT HERE} * from (
select *, ROW_NUMBER() over (order by {ORDER FIELD}) as r_n_n
from {YOUR TABLES} where {OTHER OPTIONAL FILTERS}
) xx where r_n_n >={OFFSET HERE}
Remarque:
cette solution ne fonctionnera que dans SQL Server 2005 ou supérieur, car c'était à ce moment-là qu'elle a ROW_NUMBER()
été implémentée.
AS xx
Vous pouvez utiliser ROW_NUMBER dans une expression de table commune pour y parvenir.
;WITH My_CTE AS
(
SELECT
col1,
col2,
ROW_NUMBER() OVER(ORDER BY col1) AS row_number
FROM
My_Table
WHERE
<<<whatever>>>
)
SELECT
col1,
col2
FROM
My_CTE
WHERE
row_number BETWEEN @start_row AND @end_row
Pour moi, l'utilisation de OFFSET et FETCH ensemble était lente, j'ai donc utilisé une combinaison de TOP et OFFSET comme celle-ci (ce qui était plus rapide):
SELECT TOP 20 * FROM (SELECT columname1, columname2 FROM tablename
WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname
Remarque: Si vous utilisez TOP et OFFSET ensemble dans la même requête comme:
SELECT TOP 20 columname1, columname2 FROM tablename
WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS
Ensuite, vous obtenez une erreur, donc pour utiliser TOP et OFFSET ensemble, vous devez le séparer avec une sous-requête.
Et si vous devez utiliser SELECT DISTINCT, la requête est comme:
SELECT TOP 20 FROM (SELECT DISTINCT columname1, columname2
WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname
Remarque: l'utilisation de SELECT ROW_NUMBER avec DISTINCT n'a pas fonctionné pour moi.
SELECT TOP 20 id FROM table1 where id > 10 order by date OFFSET 20 rows
, vous devez le transformer comme SELECT TOP 20 * FROM (SELECT id FROM table1 where id > 10 order by date OFFSET 20 ROWS) t1
. Je modifierai ma réponse. Merci et excusez-moi mon anglais.
Un autre échantillon:
declare @limit int
declare @offset int
set @offset = 2;
set @limit = 20;
declare @count int
declare @idxini int
declare @idxfim int
select @idxfim = @offset * @limit
select @idxini = @idxfim - (@limit-1);
WITH paging AS
(
SELECT
ROW_NUMBER() OVER (order by object_id) AS rowid, *
FROM
sys.objects
)
select *
from
(select COUNT(1) as rowqtd from paging) qtd,
paging
where
rowid between @idxini and @idxfim
order by
rowid;
Il y a ici quelqu'un qui parle de cette fonctionnalité dans sql 2011, c'est triste qu'ils choisissent un mot-clé un peu différent "OFFSET / FETCH" mais ce n'est pas standart alors ok.
En ajoutant une légère variation à la solution d'Aaronaught, je paramètre généralement le numéro de page (@PageNum) et la taille de la page (@PageSize). De cette façon, chaque événement de clic de page envoie simplement le numéro de page demandé avec une taille de page configurable:
begin
with My_CTE as
(
SELECT col1,
ROW_NUMBER() OVER(ORDER BY col1) AS row_number
FROM
My_Table
WHERE
<<<whatever>>>
)
select * from My_CTE
WHERE RowNum BETWEEN (@PageNum - 1) * (@PageSize + 1)
AND @PageNum * @PageSize
end
Le plus proche que je pourrais faire est
select * FROM( SELECT *, ROW_NUMBER() over (ORDER BY ID ) as ct from [db].[dbo].[table] ) sub where ct > fromNumber and ct <= toNumber
Ce qui je suppose similaire à select * from [db].[dbo].[table] LIMIT 0, 10
-- @RowsPerPage can be a fixed number and @PageNumber number can be passed
DECLARE @RowsPerPage INT = 10, @PageNumber INT = 2
SELECT *
FROM MemberEmployeeData
ORDER BY EmployeeNumber
OFFSET @PageNumber*@RowsPerPage ROWS
FETCH NEXT 10 ROWS ONLY
@nombre_row :nombre ligne par page
@page:numero de la page
//--------------code sql---------------
declare @page int,@nombre_row int;
set @page='2';
set @nombre_row=5;
SELECT *
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY etudiant_ID ) AS RowNum, *
FROM etudiant
) AS RowConstrainedResult
WHERE RowNum >= ((@page-1)*@nombre_row)+1
AND RowNum < ((@page)*@nombre_row)+1
ORDER BY RowNum
Puisque personne n'a encore fourni ce code:
SELECT TOP @limit f1, f2, f3...
FROM t1
WHERE c1 = v1, c2 > v2...
AND
t1.id NOT IN
(SELECT TOP @offset id
FROM t1
WHERE c1 = v1, c2 > v2...
ORDER BY o1, o2...)
ORDER BY o1, o2...
Les points importants:
@limit
peut être remplacé par le nombre de résultats à récupérer,@offset
est le nombre de résultats à ignorerwhere
et order by
clause, et fournira des résultats incorrects s'ils ne sont pas synchronisésorder by
est-il explicitement si c'est ce qu'il fautEn particulier pour SQL-SERVER, vous pouvez y parvenir de différentes manières. Pour un exemple concret, nous avons pris la table Customer ici.
Exemple 1: avec "SET ROWCOUNT"
SET ROWCOUNT 10
SELECT CustomerID, CompanyName from Customers
ORDER BY CompanyName
Pour renvoyer toutes les lignes, définissez ROWCOUNT sur 0
SET ROWCOUNT 0
SELECT CustomerID, CompanyName from Customers
ORDER BY CompanyName
Exemple 2: avec "ROW_NUMBER et OVER"
With Cust AS
( SELECT CustomerID, CompanyName,
ROW_NUMBER() OVER (order by CompanyName) as RowNumber
FROM Customers )
select *
from Cust
Where RowNumber Between 0 and 10
Exemple 3: Avec "OFFSET et FETCH", mais avec ce "ORDER BY" est obligatoire
SELECT CustomerID, CompanyName FROM Customers
ORDER BY CompanyName
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY
J'espère que cela vous aide.
Depuis, je teste plus de fois ce script plus utile de 1 million d'enregistrements chaque page 100 enregistrements avec pagination fonctionnent plus rapidement mon PC exécute ce script 0 sec alors que le comparatif avec mysql a sa propre limite et un décalage d'environ 4,5 sec pour obtenir le résultat.
Quelqu'un peut manquer de comprendre Row_Number () trier toujours par champ spécifique. Au cas où nous aurions besoin de définir uniquement la ligne dans la séquence, utilisez:
SELECT TOP {LIMIT} * FROM (
SELECT TOP {LIMIT} + {OFFSET} ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS ROW_NO,*
FROM {TABLE_NAME}
) XX WHERE ROW_NO > {OFFSET}
Explique: