Сортировка результатов. Order by
При выборке данных из БД мы можем сортировать извлекаемые данные в нужном нам порядке. Использование сортировки поможет сделать получаемые данные более удобочитаемыми и воспринимаемыми для анализа человеком.
Подготовка тестовых данных
Создадим таблицу, которая будет содержать список блюд ресторана:
create table dishes(
name varchar2(100) not null,
price number(5,2) not null,
rating number(5)
);
comment on column dishes.name is 'Наименование блюда';
comment on column dishes.price is 'Стоимость за одну порцию';
comment on column dishes.rating is 'Популярность блюда';
insert into dishes(name, price, rating)
values ('Макароны с сыром', 20.56, 320);
insert into dishes(name, price, rating)
values ('Борщ', 10, 130);
insert into dishes(name, price, rating)
values ('Чай с лимоном', 1.34, 270);
insert into dishes(name, price, rating)
values ('Чай с молоком', 1.20, 280);
insert into dishes(name, price, rating)
values ('Свиная отбивная', 30.50, 320);
insert into dishes(name, price, rating)
values ('Овощной салат', 5.70, null);Овощной салат - новинка в меню, и его еще не успели оценить посетители; Именно поэтому в колонке rating содержится null. Конечно, здесь возможны варианты - например, можно было хранить значение 0 для обозначения отсутствия оценок блюда посетителями, но для демонстрационных целей мы здесь будем хранить null.
Сортировка по возрастанию. Asc
Для того, чтобы получить данные в определенном порядке, используется конструкция order by. Для того, чтобы сортировка выполнялась по возрастанию, к конструкции order by добавляется атрибут asc.
Получим все блюда в из меню и отсортируем их по стоимости начиная с дешевых и заканчивая самыми дорогими:
select *
from dishes
order by price asc| NAME | PRICE | RATING |
|---|---|---|
| Чай с молоком | 1.2 | 280 |
| Чай с лимоном | 1.34 | 270 |
| Овощной салат | 5.7 | - |
| Борщ | 10 | 130 |
| Макароны с сыром | 20.56 | 320 |
| Свиная отбивная | 30.5 | 320 |
Сортировка может выполняться одновременно по нескольким полям. Давайте добавим сортировку по рейтингу блюд начиная от самых непопулярных и заканчивая самыми популярными блюдами. При этом, кроме рейтинга мы будем сортировать блюда по стоимости - от дешевых к дорогим:
select *
from dishes
order by rating asc, price asc| NAME | PRICE | RATING |
|---|---|---|
| Борщ | 10 | 130 |
| Чай с лимоном | 1.34 | 270 |
| Чай с молоком | 1.2 | 280 |
| Макароны с сыром | 20.56 | 320 |
| Свиная отбивная | 30.5 | 320 |
| Овощной салат | 5.7 | - |
Как видно, блюда, которые имеют одинаковый рейтинг, расположились в порядке возрастания их цен.
Сортировка по убыванию. Desc
Для сортировки по убыванию используется desc.
Например, для получения списка блюд начиная от самых популярных и заканчивая самыми непопулярными, можно написать следующий запрос:
select *
from dishes
order by rating desc| NAME | PRICE | RATING |
|---|---|---|
| Овощной салат | 5.7 | - |
| Макароны с сыром | 20.56 | 320 |
| Свиная отбивная | 30.5 | 320 |
| Чай с молоком | 1.2 | 280 |
| Чай с лимоном | 1.34 | 270 |
| Борщ | 10 | 130 |
Порядок сортировки по-умолчанию
Если в конструкции order by не указывать порядок сортировки, то oracle будет производить сортировку по возрастанию.
Т.е. следующий запрос:
select *
from dishes
order by price asc, rating ascАналогичен следующему:
select *
from dishes
order by price, ratingСортировка по порядковому номеру
Вместо указания колонки, по которой должна производиться сортировка, можно указать ее порядковый номер в выборке. Следующие 2 запроса идентичны:
select price, rating
from dishes
order by price, ratingselect price, rating
from dishes
order by 1, 2Однако, такого подхода следует избегать, и вот почему.
Предположим, мы написали следующий запрос:
select name, price
from dishes
order by 2 descЭтот запрос выводит список блюд начиная от самых дорогих и заканчивая самыми дешевыми:
| NAME | PRICE |
|---|---|
| Свиная отбивная | 30.5 |
| Макароны с сыром | 20.56 |
| Борщ | 10 |
| Овощной салат | 5.7 |
| Чай с лимоном | 1.34 |
| Чай с молоком | 1.2 |
Проходит несколько месяцев, и мы решаем извлекать кроме наименования блюда и его цены еще и рейтинг. Пишется следующий запрос:
select name, rating, price
from dishes
order by 2 desc| NAME | RATING | PRICE |
|---|---|---|
| Овощной салат | - | 5.7 |
| Макароны с сыром | 320 | 20.56 |
| Свиная отбивная | 320 | 30.5 |
| Чай с молоком | 280 | 1.2 |
| Чай с лимоном | 270 | 1.34 |
| Борщ | 130 | 10 |
Но эти данные идут не в том порядке, который нам нужен! Они отсортированы по рейтингу, а не по стоимости. Это произошло потому, что колонка с ценой теперь третья по счету, а не вторая, и при добавлении в выборку еще одной колонки нужно было проверить order by - блок и изменить порядковый номер для сортировки.
Nulls last. Nulls first
Сортировка производится по определенным значениям. Но что делать, если значение в колонке отсутствует, т.е. в нем содержится null?
Здравый смысл подсказывает, что сортировка по null-значениям невозможна.
Но мы можем указать, где должны располагаться null -значения при сортировке в начале или конце. Достигается это путем использования конструкций nulls last и nulls first. Использование первой разместит все null - значения в конце, а второй - в начале.
select *
from dishes
order by rating nulls first| NAME | PRICE | RATING |
|---|---|---|
| Овощной салат | 5.7 | - |
| Борщ | 10 | 130 |
| Чай с лимоном | 1.34 | 270 |
| Чай с молоком | 1.2 | 280 |
| Свиная отбивная | 30.5 | 320 |
| Макароны с сыром | 20.56 | 320 |
select *
from dishes
order by rating nulls last| NAME | PRICE | RATING |
|---|---|---|
| Борщ | 10 | 130 |
| Чай с лимоном | 1.34 | 270 |
| Чай с молоком | 1.2 | 280 |
| Свиная отбивная | 30.5 | 320 |
| Макароны с сыром | 20.56 | 320 |
| Овощной салат | 5.7 | - |