많은 애플리케이션에는 데이터베이스 테이블의 데이터를 한 번에 한 페이지씩 표시하는 그리드가 있습니다. 또한 대부분의 애플리케이션은 사용자가 페이지당 레코드 수를 선택하고, 열을 기준으로 정렬하고, 결과를 앞뒤로 탐색할 수 있습니다.
전체 테이블을 클라이언트로 가져온 다음 클라이언트에서 데이터를 필터링하지 않고 이 패턴을 구현하는 좋은 알고리즘은 무엇일까요? 사용자에게 표시하려는 레코드만 가져오려면 어떻게 해야 할까요?
LINQ가 솔루션을 단순화하나요?
MS SQL Server 2005 이상에서는 ROW_NUMBER()이 작동하는 것 같습니다:
T-SQL: ROW_NUMBER()를 사용한 페이징
DECLARE @PageNum AS INT;
DECLARE @PageSize AS INT;
SET @PageNum = 2;
SET @PageSize = 10;
WITH OrdersRN AS
(
SELECT ROW_NUMBER() OVER(ORDER BY OrderDate, OrderID) AS RowNum
,OrderID
,OrderDate
,CustomerID
,EmployeeID
FROM dbo.Orders
)
SELECT *
FROM OrdersRN
WHERE RowNum BETWEEN (@PageNum - 1) * @PageSize + 1
AND @PageNum * @PageSize
ORDER BY OrderDate
,OrderID;
MyDataContext db = new MyDataContext();
var results = db.Products
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
Sql Server 를 실행하는 LINQ 는 SQL 로 변환 프로필러 사실을 이 질의에서는 비슷한:
SELECT [ProductId], [Name], [Cost], and so on...
FROM (
SELECT [ProductId], [Name], [Cost], [ROW_NUMBER]
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [Name]) AS [ROW_NUMBER],
[ProductId], [Name], [Cost]
FROM [Products]
)
WHERE [ROW_NUMBER] BETWEEN 10 AND 20
)
ORDER BY [ROW_NUMBER]
분명 (영어:
기본적으로 두 가지 방법이 있는데 하고 쪽매김 데이터베이스 (I& # 39 m, 가정, re you& # 39 사용하여 SQL Server):
다른 %s/dbase/ext_table. ROW_NUMBER () 함수 () '순위' 를 통해 설명한 레온티에프의 페이징에 수행하는 데 사용할 수 있습니다. # 39 의 가치가 있는 it& 거론하며 SQL 표준 SQL Server 2012년 마지막으로 에 대한 지원을 '오프셋입니다. 페치할 ' 절:
SELECT first_name, last_name, score
FROM players
ORDER BY score DESC
OFFSET 40 ROWS FETCH NEXT 10 ROWS ONLY
There is an 덜 알려져 있지만, 완전히 다른, 훨씬 더 빠르게 수행할 수 있는 페이징의 SQL. 이것은 종종 " 말라실로 method",) 이라고 한다. 설명대로 이 블로그 포스트는 여기.
SELECT TOP 10 first_name, last_name, score
FROM players
WHERE (score < @previousScore)
OR (score = @previousScore AND player_id < @previousPlayerId)
ORDER BY score DESC, player_id DESC
이 값은 레코드 '와' '마지막' @previousScore @previousPlayerId 값을 각각 이전 페이지의. 이 ", next" 페치할 수 있습니다. 호출이네요 Order BY 경우 '는' ',', '대신' > 방향선이 ASC 사용하여 간단히.
위의 방법을 통해 4 페이지 이동 없이 즉시 delaymins 첫 반입됨 이전 40 레코드는유지합니다. 건너뛰려면 훨씬 많지만, 원하지 않는 겁니다. 그 대신 훨씬 빠르게 할 수 있을 수 있는 시간을 확보하십시오 쿼리하지 페치할 data-in 상수입니다 따라 인덱스화를. 또한, 기본 데이터 변경, stable" 상관없이 페이지에 " 거주하리라 경우 (예를 들어 1 페이지에서 동시에 you& # 39, re on 4 페이지).
이것은 웹 애플리케이션을 구현할 때 가장 좋은 방법은 더 data-in 페이징의 게으른 로드중, 예를 들어.
Note 를 " 말라실로 method"; [크리스트 페이징의] 는 eschweiler-clarke (https://stackoverflow.com/a/3215973/521799).
LINQ 와 익명 클래스에서 람다 표현식 및 .Net 3.5 hugely 단순화됩니다 이러한 종류의 것.
쿼리하지 데이터베이스입니까:
var customers = from c in db.customers
join p in db.purchases on c.CustomerID equals p.CustomerID
where p.purchases > 5
select c;
레코드 수가 당 페이지:
customers = customers.Skip(pageNum * pageSize).Take(pageSize);
모든 열에 의해 정렬:
customers = customers.OrderBy(c => c.LastName);
선택된 필드만 가져오는 서버에서:
var customers = from c in db.customers
join p in db.purchases on c.CustomerID equals p.CustomerID
where p.purchases > 5
select new
{
CustomerID = c.CustomerID,
FirstName = c.FirstName,
LastName = c.LastName
};
이 익명 클래스에서 속성에 액세스할 수 있는 정적으로 입력되었는지 만듭니다.
var firstCustomer = customer.First();
int id = firstCustomer.CustomerID;
결과가 나올 수 있으므로, t # 39 는 기본적으로 쿼리합니다 게으른 로드됨 aren& 스토리지스코프는 때까지 데이터를 데이터베이스에 대한 실제 필요한. Net 에서는 linq 의 등도 크게 단순화됩니다 유지하면, 단 한 업데이트뿐 다타콘테스트 변경 사항이 있는 업데이트하려면 필드용 변경할 수 있습니다.
내가 몇 가지 솔루션을 사용할 수 있는 MS SQL 2005년.
그 중 하나가 ROW_NUMBER () 는. 하지만 개인적으로 don& ROW_NUMBER (), t, t # 39 와 같은 doesn& # 39 사용할 수 있기 때문에 큰 결과를 (DB 어떤 난 작동합니까 가 굉장히 큰 - 1TB 이상의 데이터 실행 - 두 번째 ᅳ 아시다시피 수천 명의 쿼리합니다 대량량 소셜 네트워킹 사이트).
여기 내 좋아하는 솔루션입니다.
내아기마저도 종류의 코드를 사용하여 dtep T-SQL.
@page = 2 -- input parameter
@size = 10 -- can be optional input parameter
if @page < 1 then begin
@page = 1 -- check page number
end
@start = (@page-1) * @size + 1 -- @page starts at record no @start
-- find the beginning of page @page
SELECT TOP (@start)
@forename = forename,
@surname = surname
@id = id
FROM
users
ORDER BY
forename,
surname,
id -- to keep correct order in case of have two John Smith.
-- select @size records starting from @start
SELECT TOP (@size)
id,
forename,
surname
FROM
users
WHERE
(forename = @forename and surname = @surname and id >= @id) -- the same name and surname, but bigger id
OR (forename = @forename and surname > @surname) -- the same name, but bigger surname, id doesn't matter
OR (forename > @forename) -- bigger forename, the rest doesn't matter
ORDER BY
forename,
surname,
id
이에 대해 토론을 할 수는 없을 것 Here
이 기법은 데이터베이스 gets 에서 150,000 선 78ms 의 페이지 번호 100,000
>. 즉, 첫 페이지에: employeeid 로카운트 사용하여 최적화기 지식과 설정되었습니다 저장됩니까 요청되었습니다 는 로컬 변수 kingdome. seattle. 될 수 있습니다. 로카운트 설정할 수 있는 최대 레코드 다음, 즉 요청되었습니다 @maximumRows. 이 결과 집합을 페이징의 보다 효율적으로 사용할 수 있습니다. 또한 기존 인덱스화합니다 때문에 이 방법을 사용하여 테이블에서 활용하여 직접 댁이라면 기본 테이블 아닌 로칼에서 만든 테이블.
나는 내가 두렵도 판단할 수 없는 경우 현재 수락됨 오토메이티드 것보다 낫다.