SQL Server için LIMIT ve OFFSET eşdeğeri?


172

PostgreSQL'de , sonuç kümelerinin çok kolay sayfalandırılmasına olanak tanıyan Limitve Offsetanahtar sözcükleri vardır.

SQL Server için eşdeğer sözdizimi nedir?


Sql server 2012 için bu özellik kolay bir şekilde uygulanır. Cevabımı
Somnath Muluk

Bu soruyu sorduğunuz için teşekkür ederiz, MySQL'den MsSQL'e geçmeye zorlanıyoruz :(
tempcke

SQL Server'daki sonraki ifadeyi sıraya göre sıra ile kullanabilirsiniz. Deneyin o youtu.be/EqHkAiiBwPc
Amresh Kumar Singh

Yanıtlar:


139

Eşdeğer LIMITolduğunu SET ROWCOUNT, ancak genel sayfalama istiyorsanız böyle bir sorgu yazmak için iyidir:

;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

Buradaki avantaj, sayfalama seçeneklerinizi değiştirmeye karar vermeniz durumunda (veya kullanıcının bunu yapmasına izin vermeniz durumunda) ofset ve limitin parametrelendirilmesidir.

Not:@Offset parametre de normal sıfır tabanlı endeksleme daha bu oldukça için bir tabanlı indeksleme kullanmalıdır.


22
Şimdi yaşlı. Sql Server 2012 ve üzeri OFSET / FETCH'i destekleyin
Joel Coehoorn

31
@JoelCoehoorn Eski değil. Ben sadece geçmişte sadece mysql kullanarak SLQ Server 2008 kullanarak projeye atandı ...
Cthulhu

Bu oldukça iyi ama biraz ajusted olması gerekiyorWHERE RowNum >= (@Offset + 1)
Eric Herlitz

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

2
@Aaronaught 200 bin Tablekayıt varsa, önce hepsini alır, sonra sınır uygular? Bu sorgu etkili mi?
Jigar

231

Bu özellik SQL Server 2012'de artık daha kolay. SQL Server 2012'den itibaren çalışıyor.

SQL Server'da 11 ila 20 satır seçmek için ofset ile sınırlayın:

SELECT email FROM emailTable 
WHERE user_id=3
ORDER BY Id
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
  • OFFSET: atlanan satır sayısı
  • NEXT: gerekli sonraki satır sayısı

Referans: https://docs.microsoft.com/tr-tr/sql/t-sql/queries/select-order-by-clause-transact-sql?view=sql-server-2017


4
SQL_CALC_FOUND_ROWSBunu kullanırken bir eşdeğer var mı ?
Petah

1
@Petah @@ Rowcount sanırım size verecek
Rob Sedgwick

GOTCHA: Bunu bir CTE içinden kullanamazsınız. Ana sorguda kullanılmalıdır. Döndürülen satır miktarını (sayfalandırma) sınırlamak ve daha sonra satırları belirlemek yerine, pahalı hesaplamayı yapmak yerine daha sonra döndürülen 10 kadar satıra pahalı bir hesaplama yapmak ve sonra ihtiyacım olanı atlamak / almak istedim. @ Aaronaught'un cevabı, bir CTE içindeki satırları kısıtlamak isteyenler için işe yarayacaktır.
Derreck Dean

@Somnath Muluk Bu ofset ve getirme, 1000000 ofseti ile daha yüksek hacimli veri örneği için çok zaman alıyor. Bununla nasıl başa çıkabilirim.
Saroj Shrestha

1
@SarojShrestha: Bu Ofset ve Getirme sorunu değil. Tablonuzun mimarisini şimdi tekrar ziyaret etmelisiniz. Tabloları bölümlendirmeyi, veri satırınızı ve farklı sütun türlerini ve toplam tablo boyutunu göz önünde bulundurun, düzenli olarak gerekmiyorsa bazı satırları arşivlemeyi düşünün, sunucu özelliklerinizi kontrol edin.
Somnath Muluk

23
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}

Not: Bu çözüm ROW_NUMBER(), uygulandığı zamandan bu yana yalnızca SQL Server 2005 veya sonraki sürümlerde çalışır.


Bu sorguyu bir süredir kullanıyorum ve bunun için harika çalışıyor. Sadece 'xx'in neyi temsil ettiğini merak ediyorum.
Urbley

alt sorgu bir ad gerektirir. Ben kullanmıyorum çünkü sadece xx koymak
jorgeu

2
Xx sadece bir tablo diğer adıdır. AS xx
Dediyseniz

kimse nasıl bu sorguda katılmak yaptı biliyor?
Drenyl

12

Bunu başarmak için bir Ortak Tablo İfadesinde ROW_NUMBER kullanabilirsiniz.

;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

4

Benim için OFFSET ve FETCH birlikte kullanımı yavaştı, bu yüzden TOP ve OFFSET'in bir kombinasyonunu kullandım (bu daha hızlıydı):

SELECT TOP 20 * FROM (SELECT columname1, columname2 FROM tablename
    WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname

Not: TOP ve OFFSET işlevlerini aşağıdaki gibi aynı sorguda birlikte kullanırsanız:

SELECT TOP 20 columname1, columname2 FROM tablename
    WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS

Sonra bir hata alırsınız, bu yüzden TOP ve OFFSET'i birlikte kullanmak için bir alt sorgu ile ayırmanız gerekir.

Ve SELECT DISTINCT kullanmanız gerekiyorsa, sorgu aşağıdaki gibidir:

SELECT TOP 20 FROM (SELECT DISTINCT columname1, columname2
    WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname

Not: DISTINCT ile SELECT ROW_NUMBER kullanımı benim için çalışmadı.


1
"Bir TOP bir ofset ile aynı sorgu veya alt sorguda kullanılamaz."
MichaelRushton

Haklısın @MichaelRushton, aynı sorguda veya aynı alt sorguda kullanılamaz, sonra ayırmak için bir alt sorgu kullanmanız gerekir. Eğer SQL'iniz varsa SELECT TOP 20 id FROM table1 where id > 10 order by date OFFSET 20 rows, onu dönüştürmeniz gerekir SELECT TOP 20 * FROM (SELECT id FROM table1 where id > 10 order by date OFFSET 20 ROWS) t1. Cevabımı düzenleyeceğim. Teşekkürler ve özür dilerim İngilizcem.
sebasdev

2

Başka bir örnek:

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;

15
Anti-microsoft nefret söyleminizi kaldırdım. Burada kutsal savaşları tartışmayın; soruları öznel olmayan bir şekilde yanıtlayıp sormanız yeterlidir.
Earlz

2

Orada burada bu sql 2011 yılında özelliği, üzgün onlar "FETCH / OFFSET" biraz farklı anahtar kelime seçebilir onun ama onun standart sonra tamam değil yaklaşık birileri söylüyorum.


2

Aaronaught'un çözümüne küçük bir değişiklik ekleyerek, genellikle sayfa numarasını (@PageNum) ve sayfa boyutunu (@PageSize) parametrelendiririm. Bu şekilde, her sayfa tıklama etkinliği yapılandırılabilir bir sayfa boyutuyla birlikte istenen sayfa numarasında gönderilir:

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

2

En yakın yapabileceğim

select * FROM( SELECT *, ROW_NUMBER() over (ORDER BY ID ) as ct from [db].[dbo].[table] ) sub where ct > fromNumber  and ct <= toNumber

Sanırım benzer select * from [db].[dbo].[table] LIMIT 0, 10


1
select top (@TakeCount) * --FETCH NEXT
from(
    Select  ROW_NUMBER() OVER (order by StartDate) AS rowid,*
    From YourTable
)A
where Rowid>@SkipCount --OFFSET

1
@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

1

Henüz kimse bu kodu sağlamadığından:

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

Önemli noktalar:

  • ORDER BY aynı olmalı
  • @limit alınacak sonuç sayısı ile değiştirilebilir,
  • @offset atlanacak sonuç sayısı
  • Daha verimli olabileceğinden lütfen performansı önceki çözümlerle karşılaştırın
  • bu çözüm çoğalır whereve order byyan tümceleri içerir ve senkronize olmadıkları takdirde yanlış sonuçlar verir
  • Öte yandan order byihtiyaç duyulan şey açıkça varsa

1
-- @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

1

Özellikle SQL-SERVER için bunu birçok farklı şekilde başarabilirsiniz. Gerçek örnek için burada Müşteri tablosunu aldık.

Örnek 1: "SET ROWCOUNT" ile

SET ROWCOUNT 10
SELECT CustomerID, CompanyName from Customers
ORDER BY CompanyName

Tüm satırları döndürmek için ROWCOUNT değerini 0 olarak ayarlayın

SET ROWCOUNT 0  
SELECT CustomerID, CompanyName from Customers
    ORDER BY CompanyName

Örnek 2: "ROW_NUMBER ve OVER" ile

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

Örnek 3: "OFSET ve FETCH" ile, ancak bu "ORDER BY" ile zorunludur

SELECT CustomerID, CompanyName FROM Customers
ORDER BY CompanyName
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY

Umarım bu size yardımcı olur.


-1

SQL sunucusunda TOP'u ROW_NUMBER () ile birlikte kullanırsınız


-1

Çünkü, bu komut dosyası daha fazla kez 1 milyon kayıt daha yararlı test her sayfa 100 kayıt sayfalama ile daha hızlı çalışır benim PC bu komut dosyası 0 saniye yürütürken mysql ile karşılaştırmak kendi sınırı var ve sonuç almak için yaklaşık 4.5 saniye ofset.

Birisi her zaman belirli bir alana göre sıralıyor Row_Number () anlayışını kaçırabilir. Sadece sırayla satır tanımlamamız gerektiğinde:

ROW_NUMBER () ÜZERİNDE (SİPARİŞ VER (NULL SEÇ))

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}

Açıklamak:

  • {LIMIT}: Her sayfa için kayıt sayısı
  • {OFFSET}: Atlama kaydı sayısı

2
Bu kod, sorunun nasıl ve neden çözüldüğüne dair bir açıklama da dahil olmak üzere soruyu çözebilir, ancak gönderinizin kalitesini artırmaya yardımcı olabilir ve muhtemelen daha fazla oyla sonuçlanır. Sadece şimdi soran kişi için değil, gelecekte okuyucular için soruyu cevapladığınızı unutmayın. Lütfen açıklama eklemek için cevabınızı düzenleyin ve hangi sınırlamaların ve varsayımların geçerli olduğunu belirtin.
Brian
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.