#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() является причиной того, как медленно выполняется запрос.