2008-10-23 2 views
7

Northwind 데이터베이스를 사용하고 있고 다른 매개 변수 중에서도 포함 된 저장 프로 시저를 통해 쿼리를 실행하고 싶습니다. 다음 페이지 매김이 시작되는SQL Server 2005에서 ROW_NUMBER() OVER()를 사용하여 다른 열에서 정렬을 사용하여 페이지가 매겨진 쿼리

  • @Offset 정렬을 위해 사용되는 열을 나타 내기 위해,
  • @Limit
  • 페이지 크기를 나타 내기 위해,
  • @SortColumn을 나타 내기 위해,
  • ascending 또는 descendant 정렬을 나타내는

결과 집합에는 수천 개의 행이 포함되어 있으므로 캐싱은 옵션이 아니므로 데이터베이스에서 페이지 매김을 수행하는 것이 좋습니다. 또한 VIEWSTATE를 사용하면 IMO로 간주되지 않습니다. SQL Server 2005를 아시다시피

는 각 파티션의 첫 번째 행 1에서 시작하여, 결과 세트의 파티션 내에서 행의 일련 번호를 반환하는 기능 ROW_NUMBER을 제공합니다.

우리는 (이 예에서는 오) 모든 반환 열에서 정렬 할 필요 및 동적 SQL은 옵션이 아닙니다, 그래서 우리는 두 가지 가능성이 있습니다 IF ... ELSE ...을 많이 사용하고 지옥 유지하는 것입니다 (10 개) 쿼리를 갖는, 또는을 가진 다음과 같은 쿼리 :

WITH PaginatedOrders AS (
    SELECT 
     CASE (@SortColumn + ':' + @SortDirection) 
      WHEN 'OrderID:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID ASC) 
      WHEN 'OrderID:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID DESC) 
      WHEN 'CustomerID:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.CustomerID ASC) 
      WHEN 'CustomerID:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.CustomerID DESC) 
      WHEN 'EmployeeID:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.EmployeeID ASC) 
      WHEN 'EmployeeID:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.EmployeeID DESC) 
      WHEN 'OrderDate:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderDate ASC) 
      WHEN 'OrderDate:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderDate DESC) 
      WHEN 'ShippedDate:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID ASC) 
      WHEN 'ShippedDate:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID DESC) 
     END AS RowNumber, 
     OrderID, CustomerID, EmployeeID, OrderDate, ShippedDate 
    FROM Orders 
    -- WHERE clause goes here 
) 
SELECT 
    RowNumber, OrderID, CustomerID, EmployeeID, OrderDate, ShippedDate, 
    @Offset, @Limit, @SortColumn, @SortDirection 
FROM PaginatedOrders 
WHERE RowNumber BETWEEN @Offset AND (@Offset + @Limit - 1) 
ORDER BY RowNumber 

나는 다른 인수와 함께, 쿼리를 여러 번 시도했습니다, 그 기능이 실제로 꽤 좋은,하지만 스틸 사진이 다른 방법을 최적화 할 수있는 것 같습니다.

이 쿼리에 문제가 있습니까? 그렇지 않으면 다음과 같이됩니다. 당신은 다른 접근법을 제안합니까?

+0

내 바보 같은 오류가 있습니다. 다시 시도하십시오. – Tomalak

답변

6

간단한 : ASC 순서가 반대의 선택, 또는 경우는 NULL (DESC)에 정렬합니다

SELECT 
    OrderID, CustomerID, EmployeeID, OrderDate, ShippedDate, 
    @Offset, @Limit, @SortColumn, @SortDirection 
FROM 
    Orders 
WHERE 
    ROW_NUMBER() OVER 
    (
    ORDER BY 
     /* same expression as in the ORDER BY of the whole query */ 
) BETWEEN (@PageNum - 1) * @PageSize + 1 AND @PageNum * @PageSize 
    /* AND more conditions ... */ 
ORDER BY 
    CASE WHEN @SortDirection = 'A' THEN 
    CASE @SortColumn 
     WHEN 'OrderID' THEN OrderID 
     WHEN 'CustomerID' THEN CustomerID 
     /* more... */ 
    END 
    END, 
    CASE WHEN @SortDirection = 'D' THEN 
    CASE @SortColumn 
     WHEN 'OrderID' THEN OrderID 
     WHEN 'CustomerID' THEN CustomerID 
     /* more... */ 
    END 
    END DESC 

.

ROW_NUMBER() 함수가 동일한 ORDER BY 표현식에서 작동하도록합니다.

+0

오늘 오후에 결과를 비교하기 위해 쿼리 플래너와 프로파일 러에서이 함수를 사용해 보겠습니다. –

+0

결과를보고 싶습니다. :-) – Tomalak

+0

정확하게이 것은 다음과 같은 에러를 낸다 :'메시지 207, 레벨 16, 상태 1, 라인 41 - 유효하지 않은 컬럼 이름 'RowNumber'.'. 나는 WITH 절을 사용할 것이다. –