LINQ's .Skip (1000) .Take (100) 'ü saf SQL'de nasıl yazabilirim?


93

.Skip()LINQ'daki yöntemin SQL eşdeğeri nedir ?

Örneğin: Belirli bir veritabanı tablosundan 1000-1100 arası satırları seçmek istiyorum.

Bu sadece SQL ile mümkün mü? Yoksa tablonun tamamını seçip ardından bellekteki satırları bulmam mı gerekiyor? Mümkünse ideal olarak bundan kaçınmak isterim, çünkü masa oldukça büyük olabilir.

Yanıtlar:


78

SQL Server 2005 ve üzeri sürümlerde ROW_NUMBER işlevini kullanabilirsiniz . Örneğin.

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 51 AND 60; --BETWEEN is inclusive

Biraz daha ayrıntı için cevabımdaki bağlantıya bakın. stackoverflow.com/questions/1744802/…
Mike Atlas

51 ve 60 ARASI - kapsayıcıdır.
Drew Miller

1
Ama bu önce hepsini seçecek ve sonra bu seçimden sadece 10 tane alacak değil mi? Yoksa ilk sorgu / görünümde zaten yalnızca 10 tane olacak mı?
Tadej

139

SQL Server 2012 ve üzeri şu sözdizimini ekledi:

SELECT *
FROM Sales.SalesOrderHeader 
ORDER BY OrderDate
OFFSET (@Skip) ROWS FETCH NEXT (@Take) ROWS ONLY

11
OFFSET komutunu kullanmak için ORDER BY ___ kullanmanız gerektiğine dikkat edin .... bir sıra olmadan sayfalamayı denemeniz gerektiğini değil.
James Haug

Ayrıca, 'yeni' sözdiziminin garip bir şekilde @skip ile doğrusal bir performans cezasına sahip olduğuna dikkat edin! Satır_sayı yaklaşımı buna sahip DEĞİLDİR (yalnızca indekslenmiş sırada test edilmiştir). 20 civarında lo @Skip için, yeni sözdizimi satır_sayı yaklaşımından daha hızlıdır.
Eske Rahn

22

LINQ to SQL, bunu ROW_NUMBER pencereleme işlevi kullanarak yapar:

  SELECT a,b,c FROM 
   (SELECT a,b,c, ROW_NUMBER() OVER (ORDER BY ...) as row_number
    FROM Table) t0
   WHERE to.row_number BETWEEN 1000 and 1100;

Bu çalışır, ancak SİPARİŞ BY dan row_number üretmek için ihtiyaç olabilir Sorgunuzda neden sunucu tarafında ve performans sorunlarına yol üzerinde sıralanmış. Bir dizin ORDER BY gereksinimini karşılayabilse bile, sorgunun sonuçları döndürmeye başlamadan önce yine de 1000 satır sayması gerekir. Çoğu zaman geliştiriciler bunu unuturlar ve 5 milyon satırlık bir tablo üzerinde sayfalandırma kontrolü yaparlar ve ilk sayfanın neden öncekinden çok daha hızlı geri döndüğünü merak ederler ...

Yine de, ROW_NUMBER () kullanmak, sıralamadan kaçınmanız koşuluyla, muhtemelen kullanım kolaylığı ile iyi performans arasındaki en iyi dengedir (ORDER BY koşulu bir indeksle karşılanabilir).


1
Ekstra performans bilgisi için teşekkürler, dikkatli olmanız ve test etmeniz gerekecek.
Ray

Test edildi ve yarım milyon satırlık tablom için, bu son sayfa ilk sayfadan yaklaşık 7 kat daha yavaş. İdeal değil, ama benim için kabul edilebilir.
Ray

6

Bunu dene:

select * from [Table-Name] order by [Column-Name] 
offset [Skip-Count] rows
FETCH NEXT [Take-Count] rows only

Misal:

select * from Personals order by Id
offset 10 rows            --------->Skip 10
FETCH NEXT 15 rows only   --------->Take 15

4

Bunu yap:

.Skip (1000) çalıştırın. LINQ to SQL veri bağlamında (100) alın ve SQL çıktısına bakın. Sizin için tanımladığınız şeyi yapan bir SQL ifadesi oluşturacaktır.

O kadar zarif olmayacak ama işi halledecek.


2
Sorulan değil.
RayLoveless

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.