LIMIT, SQL Server ile nasıl uygulanır?


Yanıtlar:


127

SQL SERVER 2005'ten başlayarak, bunu yapabilirsiniz ...

USE AdventureWorks;
GO
WITH OrderedOrders AS
(
    SELECT SalesOrderID, OrderDate,
    ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber'
    FROM Sales.SalesOrderHeader 
) 
SELECT * 
FROM OrderedOrders 
WHERE RowNumber BETWEEN 10 AND 20;

veya bunun gibi 2000 ve altı sürümler için ...

SELECT TOP 10 * FROM (SELECT TOP 20 FROM Table ORDER BY Id) ORDER BY Id DESC

6
Tabloda örneğin 14 satır varsa 2. sorgu başarısız olur. Size 5 ila 14 arasındaki satırları verir, ancak 11 ila 14 arasındaki satırları istersiniz. Genel olarak, toplam satırlar bu "sayfa" boyutunun katı olmadığı sürece, sonucun son "sayfası" için başarısız olur.
Bill Karwin

147
Böyle basit bir şeyin MS tarafından bir kez daha çok zorlaştırılması gerekiyor!
Martin

İşte benim için SQL Server Management Studio 2017'de işe yarayanlar: SEÇİN * [dbo]. <Buraya tablo adı ekleyin> NEREDE @@ ROWCOUNT ARASINDA <min buraya girin> ve <max buraya ekleyin>
Artorias2718

Harika, MS SQL Server 2017 select Statement
PatsonLeaner

58

Hantal, ama işe yarayacak.

SELECT TOP 10 * FROM table WHERE id NOT IN (SELECT TOP 10 id FROM table ORDER BY id) FROM table ORDER BY id

MSSQL'in LIMIT cümlesini ihmal etmesi suçtur, IMO. Bu tür bir geçici çözüm yapmanız gerekmez.


Bunu atlamak için başka bir öneriniz var mı?
Bigballs

En son MSSQL ile uğraşmak zorunda kaldığımda çok fazla Googling yaptım ve bulduğum en iyi çözüm buydu. Hoş değil ama işe yarıyor.
ceejayoz

Bu çözüm yalnızca sonuç kümesi benzersiz bir sütun içeriyorsa işe yarar. Herhangi bir sorgu için LIMIT'i taklit etmek genel bir çözüm değildir.
Bill Karwin

1
Şu anda benzer bir ikilem içindeyim ... Ancak, benim durumumda bıktım ... Sözde 'uzman' dba'ların bir tabloda gereksiz yere benzersiz bir anahtar olduğuna karar vermeleri daha da suçlu ... HERHANGİ BİR tablo ... Yabancı anahtarlar ve kısıtlamalar konusunu bile açmayın!
Andrew Rollings

Bununla ilgili sorun şu ki, WHERE cümleciklerini çok iyi idare edemiyor ... Benim için çalışmadığı için geçici tabloları deneyeceğim.
çirkin solgun

37

SQL SERVER 2012'den başlayarak, OFSET FETCH Maddesini kullanabilirsiniz:

USE AdventureWorks;
GO
SELECT SalesOrderID, OrderDate
FROM Sales.SalesOrderHeader 
ORDER BY SalesOrderID
    OFFSET 10 ROWS
    FETCH NEXT 10 ROWS ONLY;
GO

http://msdn.microsoft.com/en-us/library/ms188385(v=sql.110).aspx

Siparişi benzersiz olmadığında bu doğru çalışmayabilir.

Sorgu SİPARİŞ TARİHİNDE SİPARİŞ olarak değiştirilirse, döndürülen sonuç kümesi beklendiği gibi değildir.


'Birlikte' kullanmak, sorgulamayı bitirmek için yalnızca yarısı kadar zamana ihtiyaç duyar - @Leon Tayson'ın cevabına bakın. Microsoft'un işi bu kadar yavaşlatmak için ne yaptığı hakkında hiçbir fikrim yok.
isHuman

1
Neden kabul edilen cevap bu değil? Biz içindedir 2018 aşkına!
Skipper

1
@Skipper doğru. kabul edilen hala çalışıyor. Güncellemeyi yansıtması için buna oy verelim.
kronn

18

Bu, Ekim ayında sorduğum bir sorunun neredeyse aynısı: Microsoft SQL Server 2000'de MySQL LIMIT yan tümcesini taklit edin

Microsoft SQL Server 2000 kullanıyorsanız, iyi bir çözüm yoktur. Çoğu kişi, sorgunun sonucunu geçici bir tabloda IDENTITYbirincil anahtarla yakalamaya başvurmak zorundadır . Ardından, bir BETWEENkoşul kullanarak birincil anahtar sütununa göre sorgulama yapın .

Microsoft SQL Server 2005 veya sonraki bir sürümünü kullanıyorsanız, bir ROW_NUMBER()işleviniz vardır, böylece aynı sonucu alabilir ancak geçici tablodan kaçınabilirsiniz.

SELECT t1.*
FROM (
    SELECT ROW_NUMBER OVER(ORDER BY id) AS row, t1.*
    FROM ( ...original SQL query... ) t1
) t2
WHERE t2.row BETWEEN @offset+1 AND @offset+@count;

Ayrıca bu yazabilirsiniz ortak tablo ifade @Leon Tayson en gösterildiği gibi cevap .


ROW_NUMBER () OVER (ORDER BY) ANSI SQL: 2003'te geçerli olduğu için puan alır, ancak SQL Server dışındaki DBMS'lerde destek çok yetersizdir. Ve tabii ki oldukça hantal ...
bobince

@bobince: Oracle, Microsoft SQL Server 2005, IBM DB2 ve PostgreSQL 8.4'ün tüm pencere işlevlerini desteklediği ortaya çıktı. Bu, SQL pazarının büyük çoğunluğunu kapsar. Destek, yalnızca MySQL, SQLite veya yukarıdaki DB'lerin eski bir sürümünü kullanıyorsanız yetersiz kalır.
Bill Karwin

16

MS SQL Server 2012'deki sonuçları şu şekilde sınırlandırıyorum:

SELECT * 
FROM table1
ORDER BY columnName
  OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY

NOT: OFFSETyalnızca birlikte veya birlikte kullanılabilir ORDER BY.

Kod satırını açıklamak için OFFSET xx ROWS FETCH NEXT yy ROW ONLY

xxTabloda, yani içinde gelen çekerek başlamak istediğiniz kayıt / satır numarasıdır: Tablo 1'de 40 kayıt varsa, yukarıdaki kod sıranın 10 ila çekerek başlayacaktır.

yyEğer tablodan çıkarmak istiyorum kayıtlar / satır sayısıdır.

Önceki örnek üzerine inşa etmek için: Tablo 1'de 40 kayıt varsa ve satır 10'dan almaya başladıysanız ve SONRAKİ 10 ( yy) kümesini kapın . Bu, yukarıdaki kodun 10. satırdan başlayıp 20'de biten tablo 1'deki kayıtları çekeceği anlamına gelir. Böylece 10 - 20 arasındaki satırları çeker.

OFFSET hakkında daha fazla bilgi için bağlantıya göz atın


12
SELECT  *
FROM    (
        SELECT  TOP 20
                t.*, ROW_NUMBER() OVER (ORDER BY field1) AS rn
        FROM    table1 t
        ORDER BY
                field1
        ) t
WHERE   rn > 10

Biraz önce kontrol ettim, ORDER BY yan tümcesinde dizine alınmış bir sütun varsa, SQL Server'ın ROW_NUMBER () koşulunda duracak kadar akıllı olduğu ortaya çıktı.
Quassnoi

9

Sözdizimsel olarak MySQL LIMIT sorgusu şuna benzer:

SELECT * FROM table LIMIT OFFSET, ROW_COUNT

Bu, Microsoft SQL Sunucusuna şu şekilde çevrilebilir:

SELECT * FROM 
(
    SELECT TOP #{OFFSET+ROW_COUNT} *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rnum 
    FROM table
) a
WHERE rnum > OFFSET

Şimdi sorgunuz şöyle select * from table1 LIMIT 10,20olacak:

SELECT * FROM 
(
    SELECT TOP 30 *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rnum 
    FROM table1
) a
WHERE rnum > 10 

2

Bu, MS Sunucusunu kullanmaktan kaçınmamın nedenlerinden biri ... ama yine de. Bazen bir seçeneğiniz olmaz (yei! Ve eski bir sürümü kullanmam gerekiyor !!).

Benim önerim sanal bir tablo oluşturmak:

Gönderen:

SELECT * FROM table

Kime:

CREATE VIEW v_table AS    
    SELECT ROW_NUMBER() OVER (ORDER BY table_key) AS row,* FROM table

Sonra sadece sorgulayın:

SELECT * FROM v_table WHERE row BETWEEN 10 AND 20

Alanlar eklenir veya kaldırılırsa, "satır" otomatik olarak güncellenir.

Bu seçenekteki temel sorun, ORDER BY'ın düzeltilmiş olmasıdır. Yani farklı bir düzen istiyorsanız, başka bir görünüm oluşturmanız gerekir.

GÜNCELLEME

Bu yaklaşımla ilgili başka bir sorun daha var: Verilerinizi filtrelemeye çalışırsanız, beklendiği gibi çalışmayacaktır. Örneğin, yaparsanız:

SELECT * FROM v_table WHERE field = 'test' AND row BETWEEN 10 AND 20

WHERE, 10 ile 20 arasındaki satırlarda bulunan verilerle sınırlı hale gelir (tüm veri kümesini aramak ve çıktıyı sınırlamak yerine).


1

Bu, SQL2000'de çalışacak çok adımlı bir yaklaşımdır.

-- Create a temp table to hold the data
CREATE TABLE #foo(rowID int identity(1, 1), myOtherColumns)

INSERT INTO #foo (myColumns) SELECT myData order By MyCriteria

Select * FROM #foo where rowID > 10

1
SELECT 
    * 
FROM 
    (
        SELECT 
            top 20              -- ($a) number of records to show
            * 
        FROM
            (
                SELECT 
                    top 29      -- ($b) last record position
                    * 
                FROM 
                    table       -- replace this for table name (i.e. "Customer")
                ORDER BY 
                    2 ASC
            ) AS tbl1 
        ORDER BY 
            2 DESC
    ) AS tbl2 
ORDER BY 
    2 ASC;

-- Examples:

-- Show 5 records from position 5:
-- $a = 5;
-- $b = (5 + 5) - 1
-- $b = 9;

-- Show 10 records from position 4:
-- $a = 10;
-- $b = (10 + 4) - 1
-- $b = 13;

-- To calculate $b:
-- $b = ($a + position) - 1

-- For the present exercise we need to:
-- Show 20 records from position 10:
-- $a = 20;
-- $b = (20 + 10) - 1
-- $b = 29;

Benim için harika bir çözümdü.
Tyde

1

Denemelisin. Aşağıdaki sorguda, gruplama ölçütü, sıralama ölçütü, Satırları atla ve satır sınırı görebilirsiniz.

select emp_no , sum(salary_amount) from emp_salary
Group by emp_no 
ORDER BY emp_no 
OFFSET 5 ROWS       -- Skip first 5 
FETCH NEXT 10 ROWS ONLY; -- limit to retrieve next 10 row after skiping rows


0

SQL'de LIMIT anahtar kelime yoktur. Yalnızca sınırlı sayıda satıra ihtiyacınız varsa, LIMIT’e benzer bir TOP anahtar sözcüğü kullanmalısınız.


0

Kimliğiniz benzersiz bir tanımlayıcı türü ise veya tablodaki kimliğiniz sıralanmamışsa, aşağıdaki gibi yapmanız gerekir.

select * from
(select ROW_NUMBER() OVER (ORDER BY (select 0)) AS RowNumber,* from table1) a
where a.RowNumber between 2 and 5



Kod olacak

2,5 sınırından * seçin

0

bunu MSSQLExpress 2017'de daha iyi kullanın.

SELECT * FROM
(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) as [Count], * FROM table1
) as a
WHERE [Count] BETWEEN 10 and 20;

- Bir Sütun [Sayım] vermek ve her satıra bir şey sipariş etmeden benzersiz bir sayım atamak ve ardından sınırlarınızı belirleyebileceğiniz yeri yeniden seçin .. :)


0

Aşağıdaki gibi sonuç almanın olası yollarından biri, bunun yardımcı olacağını umuyoruz.

declare @start int
declare @end int
SET @start = '5000';  -- 0 , 5000 ,
SET @end = '10000'; -- 5001, 10001
SELECT * FROM ( 
  SELECT TABLE_NAME,TABLE_TYPE, ROW_NUMBER() OVER (ORDER BY TABLE_NAME) as row FROM information_schema.tables
 ) a WHERE a.row > @start and a.row <= @end

0

Kolay yol

MYSQL:

SELECT 'filds' FROM 'table' WHERE 'where' LIMIT 'offset','per_page'

MSSQL:

SELECT 'filds' FROM 'table' WHERE 'where' ORDER BY 'any' OFFSET 'offset' 
ROWS FETCH NEXT 'per_page' ROWS ONLY

ORDER BY zorunludur


-2

Doğru hatırlıyorsam (SQL Server ile uğraştığımdan bu yana epey zaman geçti) şuna benzer bir şey kullanabilirsiniz: (2005 ve sonrası)

SELECT
    *
   ,ROW_NUMBER() OVER(ORDER BY SomeFields) AS [RowNum]
FROM SomeTable
WHERE RowNum BETWEEN 10 AND 20

SQL Server 2012: Msg 207, Seviye 16, Durum 1, Satır 5 Geçersiz sütun adı 'RowNum'.
e-info128

Bir yerlerde ifadenizde bir yazım hatası var gibi görünüyor. RowNum, ifadeye atadığımız isimdir. Sorununuzu kaynakla paylaşın ve topluluk size yardımcı olsun
Kris

Bu geçerli bir sözdizimi değil. WHEREAynı düzeyde tanımlanmış bir takma ada referans veremezsinizSELECT maddesi.
ypercubeᵀᴹ
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.