Załóżmy, że używam bazy danych Northwind i chciałbym uruchomić kwerendę za pomocą procedury przechowywanej, która zawiera, oprócz innych parametrów, następujące:Pośrednia kwerenda za pomocą sortowania na różnych kolumnach za pomocą ROW_NUMBER() OVER() w SQL Server 2005
@Offset
wskazać gdzie zaczyna się paginacja,@Limit
wskazać rozmiar strony,@SortColumn
wskazać kolumnę używaną do celów sortowania,@SortDirection
, aby wskazać sortowanie rosnąco lub potomka.
Chodzi o to, aby zrobić podział na strony w bazie danych, ponieważ zestaw wyników zawiera tysiące wierszy, więc buforowanie nie jest opcją (a korzystanie z funkcji VIEWSTATE nie jest nawet uważane za IMO, zasysane).
Jak wiadomo SQL Server 2005 udostępnia funkcję ROW_NUMBER który zwraca kolejny numer wiersza w rozbicie zbioru wynikowego, zaczynając od 1 dla pierwszego wiersza w każdej partycji.
Potrzebujemy sortowania na każdej zwróconej kolumnie (pięć w tym przykładzie), a dynamiczny SQL nie jest opcją, więc mamy dwie możliwości: używanie dużej liczby IF ... ELSE ...
i posiadanie 10 zapytań, co jest piekłem do utrzymania lub posiadania kwerendy tak:
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
próbowałem zapytaniu kilka razy, z różnymi argumentami, a jego wydajność jest całkiem dobry faktycznie, ale to uspokaja wygląda to może być zoptymalizowane w jakiś inny sposób.
Czy coś jest nie tak z tym zapytaniem, czy zrobiłbyś to w ten sposób? Czy proponujesz inne podejście?
Mój głupi błąd, naprawiłem to. Proszę spróbuj ponownie. – Tomalak