Сортировка результатов. 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);
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
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
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
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 asc, rating asc
Аналогичен следующему:
select *
from dishes
order by price, rating
select *
from dishes
order by price, rating
Сортировка по порядковому номеру
Вместо указания колонки, по которой должна производиться сортировка, можно указать ее порядковый номер в выборке. Следующие 2 запроса идентичны:
select price, rating
from dishes
order by price, rating
select price, rating
from dishes
order by price, rating
select price, rating
from dishes
order by 1, 2
select price, rating
from dishes
order by 1, 2
Однако, такого подхода следует избегать, и вот почему.
Предположим, мы написали следующий запрос:
select name, price
from dishes
order by 2 desc
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
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
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
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 | - |