Разбиение на страницы с группировкой

#sql #sql-server #tsql

Вопрос:

У меня есть таблица с более чем 800 тысячами записей. Эта таблица должна быть «сгруппирована» по определенному столбцу. Примером может быть:

введите описание изображения здесь

Однако с разбиением на страницы все усложняется. Я хочу показать 50 строк для каждой группы.

Это означает, что если у меня есть следующие данные:

ID Цвет Имя
1 Красный Статья № 1
2 Красный Статья № 2
3 Красный Статья № 3
4 Зеленый Статья № 4
5 Зеленый Статья № 5
6 Зеленый Статья № 6
7 Зеленый Статья № 7

И я хотел получить 2 элементы для каждой группы на странице (вместо 50 того , чтобы, ради этого примера), на странице 1 у меня было бы:

ID Цвет Имя
1 Красный Статья № 1
2 Красный Статья № 2
4 Зеленый Статья № 4
5 Зеленый Статья № 5

И на странице 2 у меня было бы:

ID Цвет Имя
3 Красный Статья № 3
6 Зеленый Статья № 6
7 Зеленый Статья № 7

Мой текущий SQL-запрос (SQL Server) для разбиения на страницы выглядит следующим образом:

 SELECT
   * 
from
   [Order] 
ORDER BY
[From] ASC
OFFSET (@PageNumber - 1) * @RowsOfPage ROWS FETCH NEXT @RowsOfPage ROWS ONLY
 

Комментарии:

1. Не полный ответ, но начните с SELECT *,ROW_NUMBER() OVER(PARTITION BY Color ORDER BY Name) AS Row FROM Order WHERE Row BETWEEN (@PageNumber -1 )*@RowsOfPage 1 AND @PageNumber*@RowsOfPage ORDER BY Color,Row

2. что такое СУБД ?

3. @VenkataramanR SQL-сервер

4. This table needs to be "grouped by" a certain column Что это certain column за образец данных, который вы опубликовали ?

5. @Беличий Цвет

Ответ №1:

Используя этот образец данных:

 CREATE TABLE Orders(Id int, Color varchar(10), Name varchar(50));
INSERT INTO Orders(Id,Color,Name) VALUES 
  (1, 'Red', 'Paper #1'),
  (2, 'Red', 'Paper #2'),
  (3, 'Red', 'Paper #3'),
  (4, 'Green', 'Paper #4'),
  (5, 'Green', 'Paper #5'),
  (6, 'Green', 'Paper #6'),
  (7, 'Green', 'Paper #7');
 

Этот запрос подойдет:

 DECLARE @PageNum int = 1;
DECLARE @PageSize int = 2;
SELECT *
FROM (
  SELECT *,ROW_NUMBER() OVER(PARTITION BY Color ORDER BY Name) AS Row
  FROM Orders
) t1
WHERE Row BETWEEN ((@PageNum-1)*@PageSize 1) AND (@PageNum*@PageSize)
ORDER BY Color,Name
 

Страница 1: http://sqlfiddle.com/#!18/748cc2/27/0
введите описание изображения здесь

Страница 2: http://sqlfiddle.com/#!18/748cc2/25/0
введите описание изображения здесь

Комментарии:

1. Это работает. Однако при очень большом столе это кажется чрезвычайно медленным. Связано ли это с использованием ROW_NUMBER() ?

2. Я должен был бы взглянуть на объяснение. Может быть любое количество факторов, некоторые из которых могут быть легко исправлены-например, предварительное вычисление начальных/конечных строк вне запроса. SQL Server может быть не в состоянии сделать вывод о том, что он должен генерировать диапазон индексов, или, возможно, вам не хватает подходящего индекса для его использования.

3. Поскольку это статическая таблица, которая никогда не изменится, я могу создать столбец под названием Строка, содержащий строку#, и создать уникальный индекс для этого столбца. Однако я не уверен, как бы я использовал этот столбец в запросе, который вы предоставили выше. Я почти уверен, что ROW_NUMBER() является причиной того, как медленно выполняется запрос.