Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
SQL.doc
Скачиваний:
19
Добавлен:
14.03.2016
Размер:
382.46 Кб
Скачать

Нумерация строк в соответствии с порядком, заданном значениями первичного ключа

Естественно, нумероваться строки должны в соответствии с некоторым порядком. Пусть этот порядок задается столбцом первичного ключа, то есть в порядке возрастания (или убывания) значений в этом единственном столбце. Для определенности предположим, что нам нужно перенумеровать модели в таблице Product, где номер модели как раз является первичным ключом. Существенным здесь является то, значения первичного ключа не содержат дубликатов и NULL-значений, в результате чего имеется принципиальная возможность установить однозначное соответствие между номером модели и номером строки в заданном порядке сортировки моделей.

Рассмотрим сначала следующий запрос:

  1. SELECT P1.model, P2.model

  2. FROM Product P1 JOIN

  3. Product P2 ON P1.model <= P2.model

Здесь выполняется соединение двух идентичных таблиц по неравенству P1.model <= P2.model, в результате чего каждая модель из второй таблицы (P2.model) будет соединяться только с теми моделями из первой таблицы (P1.model), номера которых меньше или равны номеру этой модели. В результате получим, например, что модель с минимальным номером (1121) будет присутствовать во втором столбце результирующего набора только один раз, так как она меньше или равна только самой себе. На другом конце будет находиться модель с максимальным номером, так как любая модель будет меньше или равна ей. Следовательно, модель с максимальным номером будет сочетаться с каждой моделью, и число таких сочетаний будет равно общему числу моделей в таблице Product.

Из сказанного выше ясно, что это количество раз, которое каждая из моделей встречается во втором столбце результирующего набора как раз и будет порядковым номером модели при сортировке моделей по возрастанию.

Таким образом, чтобы решить нашу задачу нумерации достаточно пересчитать модели в правом столбце, что нетрудно сделать при помощи группировки и использования агрегатной функции COUNT:

  1. SELECT COUNT(*) no, P2.model

  2. FROM Product P1 JOIN

  3. Product P2 ON P1.model <= P2.model

  4. GROUP BY P2.model

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

Если ваша СУБД поддерживает ранжирующие функции, то пронумеровать строки можно совсем просто:

  1. SELECT ROW_NUMBER() OVER(ORDER BY model) no, model

  2. FROM Product;

Функция row_number

Функция ROW_NUMBER, как следует из ее названия, нумерует строки, возвращаемые запросом. С ее помощью можно выполнить более сложное упорядочивание строк в отчете, чем то, которое дает предложение ORDER BY в рамках Стандарта SQL-92.

До появления этой функции для нумерации строк, возвращаемых запросом, приходилось использовать довольно сложный интуитивно непонятный алгоритм. Единственным достоинством данного алгоритма является то, что он будет работать практически на всех СУБД, поддерживающих стандарт SQL-92.

Используя функцию ROW_NUMBER можно:

  • задать нумерацию, которая будет отличаться от порядка сортировки строк результирующего набора;

  • создать "несквозную" нумерацию, т.е. выделить группы из общего множества строк и пронумеровать их отдельно для каждой группы;

  • использовать одновмеренно несколько способов нумерации, поскольку, фактически, нумерация не зависит от сортировки строк запроса.

Проще всего возможности функции ROW_NUMBER показать на простых примерах, к чему мы и переходим.

Пример1: Пронумеровать все рейсы из таблицы Trip в порядке возрастания их номеров. Выполнить сортировку по {id_comp, trip_no}.

  1. SELECT row_number() over(ORDER BY trip_no) num,

  2. trip_no, id_comp

  3. FROM trip

  4. WHERE ID_comp < 3

  5. ORDER BY id_comp, trip_no

Предложение OVER, с которым используется функция ROW_NUMBER задает порядок нумерации строк. При этом используется дополнительное предложение ORDER BY, которое не имеет отношения к порядку вывода строк запроса

num

trip_no

id_comp

1

1181

1

2

1182

1

3

1187

1

4

1188

1

5

1195

1

6

1196

1

7

1145

2

8

1146

2

А если требуется пронумеровать рейсы для каждой компании отдельно? Для этого нам потребуется еще одна конструкция в предложении OVER - PARTITION BY.

Конструкция PARTITION BY задает группы строк, для которых выполняется независимая нумерация. Группа определяется равенством значений в списке столбцов, перечисленных в этой конструкции, у строк, составляющих группу.

Пример2: Пронумеровать рейсы каждой компании отдельно в порядке возрастания номеров рейсов.

  1. SELECT row_number() over(partition BY id_comp ORDER BY id_comp,trip_no) num,

  2. trip_no, id_comp

  3. FROM trip

  4. WHERE ID_comp < 3

  5. ORDER BY id_comp, trip_no

num

trip_no

id_comp

1

1181

1

2

1182

1

3

1187

1

4

1188

1

5

1195

1

6

1196

1

1

1145

2

2

1146

2

PARTITION BY id_comp означает, что рейсы каждой компании образуют группу, для которой и выполняется независимая нумерация.

Отсутствие конструкции PARTITION BY, как это быо в первом примере, означает, что все строки результирующего набора образуют одну единственную группу.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]