Разное

Sql order by по нескольким полям: Как построить sql запрос сортировки по двум полям? — Хабр Q&A

Содержание

Сортировка в SQL по одному полю, затем по другому

Вы здесь:
Главная — MySQL — SQL — Сортировка в SQL по одному полю, затем по другому


Я уже как-то писал про сортировку сразу по нескольким полям в SQL. Но иногда требуется сортировка не сразу по нескольким полям, а сначала по одному, затем по-другому. Например, в курсе, который я сейчас записываю, мне потребовалось вывести 8 новинок из таблицы и отсортировать эти 8 новинок по цене. Не сразу по новизне и цене, а именно сначала новинки, а потом сортировка. Давайте с Вами разберём, как делается сортировка в SQL сначала по одному полю, затем по другому.

Безусловно, можно просто извлечь 8 новинок, а потом в PHP уже отсортировать по цене, но это весьма сомнительное решение. Вот как это можно сделать сразу в SQL:


SELECT * FROM

(SELECT * FROM `table` ORDER BY `date` DESC LIMIT 8) a

ORDER BY `price`

Как видите, получился такой достаточно хитрый запрос. Мы после первого FROM не писали название таблицы, а указали множество данных, полученных выборкой из другой таблицы. И вот из этой другой таблицы выбирается 8 новинок, а потом в полученном множестве идёт уже сортировка по цене.

Таким образом, PHP нам не потребовался, хотя абсолютное большинство в такой ситуации к этому обязательно бы прибегнули.


  • Создано 14.02.2013 21:25:36



  • Михаил Русаков

Предыдущая статья Следующая статья

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):


  1. Кнопка:

    <a href=»https://myrusakov.ru» target=»_blank»><img src=»https://myrusakov.ru/images/button.gif» alt=»Как создать свой сайт» /></a>

    Она выглядит вот так:


  2. Текстовая ссылка:
    <a href=»https://myrusakov.ru» target=»_blank»>Как создать свой сайт</a>

    Она выглядит вот так: Как создать свой сайт

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):

    [URL=»https://myrusakov.ru»]Как создать свой сайт[/URL]

Двойная сортировка на SQL

Вы здесь:
Главная — MySQL — SQL — Двойная сортировка на SQL


В большинстве случаев, когда из базы данных выводится множество записей, требуется их сортировка по какому-либо полю. Либо по алфавиту, либо по id, либо по какому-либо другому параметру. Но иногда возникает ситуация, когда требуется сделать двойную сортировку в SQL-запросе. Давайте разберём, когда она может потребоваться и, главное, как её провести.

Допустим, у нас имеется примерно такая таблица:









login

amount
a 20
a 15
b 12
c 14
b 19
с 10

Нам нужно отсортировать все записи по полю login, а затем внутри этого login отсортировать по amount. То есть чтобы у нас получился такой результат:









login

amount
a 15
a 20
b 12
b 19
с 10
c 14

К счастью, в SQL двойная сортировка делается просто элементарно:


SELECT * FROM `my_table` ORDER BY `login`, `amount`

После выполнения этого запроса Вы получите как раз требуемый результат. Вот таким простым способом делается двойная сортировка прямо в SQL-запросе.


  • Создано 12.12.2012 09:33:46



  • Михаил Русаков

Предыдущая статья Следующая статья

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):


  1. Кнопка:

    <a href=»https://myrusakov.ru» target=»_blank»><img src=»https://myrusakov.ru/images/button.gif» alt=»Как создать свой сайт» /></a>

    Она выглядит вот так:


  2. Текстовая ссылка:
    <a href=»https://myrusakov.ru» target=»_blank»>Как создать свой сайт</a>

    Она выглядит вот так: Как создать свой сайт

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):

    [URL=»https://myrusakov.ru»]Как создать свой сайт[/URL]

MySQL | Сортировка. ORDER BY

Сортировка. ORDER BY

Последнее обновление: 16.05.2018

Оператор ORDER BY сортируют значения по одному или нескольких столбцам. Например, упорядочим выборку из таблицы Products
по столбцу Price:


SELECT * FROM Products
ORDER BY Price;

Также можно производить упорядочивание данных по псевдониму столбца, который определяется с помощью оператора AS:


SELECT ProductName, ProductCount * Price AS TotalSum
FROM Products
ORDER BY TotalSum;

В качестве критерия сортировки также можно использовать сложно выражение на основе столбцов:


SELECT ProductName, Price, ProductCount
FROM Products
ORDER BY ProductCount * Price;

Сортировка по убыванию

По умолчанию данные сортируются по возрастанию, однако с помощью оператора DESC можно задать сортировку по убыванию.


SELECT ProductName, ProductCount
FROM Products
ORDER BY ProductCount DESC;

По умолчанию вместо DESC используется оператор ASC, который сортирует по возрастанию:


SELECT ProductName, ProductCount
FROM Products
ORDER BY ProductCount ASC;

Сотировка по нескольким столбцам

При сортировке сразу по нескольким столбцам все эти столбцы указываются через запятую после оператора ORDER BY:


SELECT ProductName, Price, Manufacturer
FROM Products
ORDER BY Manufacturer, ProductName;

Здесь строки сначала сортируются по столбцу Manufacturer по возрастанию. Затем если есть две строки, в которых столбец Manufacturer
имеет одинаковое значение, то они сортируются по столбцу ProductName также по возрастанию. Но опять же с помощью ASC и DESC можно отдельно для
разных столбцов определить сортировку по возрастанию и убыванию:


SELECT ProductName, Price, Manufacturer
FROM Products
ORDER BY Manufacturer ASC, ProductName DESC;

Некоторые примеры нестандартных возможностей синтаксиса Oracle SQL / Хабр

Введение

Примерно полтора года назад я сдал экзамены на OCP Advanced PL/SQL Developer, далее специфика работы несколько изменилась, и после стандартного производственного использования Oracle я занимался разработкой архитектуры двухуровневой клиент-серверной системы на основе Oracle для нужд компьютерной лингвистики. Далее был этап развития системы и решения наукоемких задач на ее основе, пришлось заниматься использованием иерархических запросов в решении нестандартных задач и другими специфическими вещами. Результатом углубления в специфику стало некоторое «проседание» базы, а значит, наступило время снова просмотреть материалы, использовавшиеся для подготовки к экзаменам.

Ниже будет приведено несколько нестандартных примеров использования sql-запросов. Такие примеры обычно приходят на ум во время просмотра конспекта, проверяются, обсуждаются с другими специалистами и забываются. В этот раз мне захотелось сохранить некоторые из них в sql-файле, позже стала понятна необходимость в комментариях к каждому запросу. Так и появилась эта заметка.

Несколько слов о специфике оператора order by

Как вы думаете, будет ли ошибка в результате выполнения данного запроса?

--Запрос №1
select * from dual
order by 1+2||dummy

Ответ: ошибки не будет, т.к. спецификация order by определена следующим образом:
ORDER BY {col(s)|expression|numeric_pos} [ASC|DESC] [NULLS FIRST|LAST];
Где expression — A sort key expression, such as numeric, string, and datetime expressions. Expression can also be a row value expression such as a scalar subquery or case expression.
Подробнее, например, здесь download.oracle.com/javadb/10.6.2.1/ref/rrefsqlj13658.html

Таким образом, мы отсортировали таблицу dual по выражению «3X», что бессмысленно, однако в качестве выражения для сортировки можно, например, использовать выражение с функцией substr. Важна сама возможность использования выражений.

Как мы знаем, таблица dual содержит один столбец, вернет ли ошибку такой запрос:

--Запрос №2
select * from dual
order by 2

А такой?

--Запрос №3
select * from dual
order by 2+0

В первом случае мы имеем дело с позиционным указанием колонок – т.е. ссылкой на колонку №2, которой не существует, соответственно, получим ошибку.

Во втором случае мы имеем дело с выражением, т.е. это уже не номер колонки, а сортировка по числу 2, аналогичная сортировке по строке «3X» в запросе №1. Поэтому ошибки не будет.

Посмотрите на следующий пример. Какой порядок строк мы получим в результате выполнения этого запроса? Будет ли ошибка?

--Запрос №4
select 3, dummy from dual
union all
select 2, dummy from dual
order by "3"

Union all не сортирует строки объединяемых множеств (в отличии от union), т.е. без order by мы получим строки в указанном в запросе порядке (union all гарантирует сохранение исходного порядка строк). Теперь настала очередь order by, главный вопрос, что такое «3» в этом случае? Поскольку у нас использованы двойные кавычки «, а не одинарные ‘, то «3» – это алиас колонки. Как известно, операции с множествами требуют использования сходных типов данных, а имена колонок берутся из первого запроса, поскольку мы явно не указали имя первой колонки, то, по умолчанию, она получила имя выражения, т.е. «3». Работа с такими алиасами показана, например, в запросе №5 (главное не забывать про аппер-кейс).

Сортировка по умолчанию – всегда asc, т.е. результаты запроса №4 сортируются по первой колонке по возрастанию. Результат: строка «2, Х», потом «3, Х».

--Запрос №5
select substr(dummy,1,1) from dual
order by "SUBSTR(DUMMY,1,1)" 

Повторим эксперимент из запроса №3 на множествах. Каким будет результат запроса?

--Запрос №6
select 3, dummy from dual
union all
select 2, dummy from dual
order by 2+0

Может показаться, что результат запроса будет следующим: строка «3, Х» потом «2, Х». Предпосылки для этого следующие: данный порядок гарантирует union all, а выражение 2+0 не повлияет на сортировку записей (что показано в запросе №7). Так бы оно и было, если бы не одно «но»: в операциях с множествами order by можно использовать только в конце составного запроса с именами или номерами столбцов первого запроса, выражения не допускаются:
For compound queries containing set operators UNION, INTERSECT, MINUS, or UNION ALL, the ORDER BY clause must specify positions or aliases rather than explicit expressions. Also, the ORDER BY clause can appear only in the last component query. The ORDER BY clause orders all rows returned by the entire compound query. download.oracle.com/docs/cd/B19306_01/server.102/b14200/queries005.htm#i2053998

Поэтому запрос №6 вернет ошибку.

--Запрос №7
select * from
        (select 3, dummy from dual
         union all
         select 2, dummy from dual)
order by 2+0

Использование not in

Наверняка, большинство людей, прошедших различные курсы, помнят, что следует избегать оператора not in, а сходную функциональность можно получить, используя операторы in либо exists. Причина такого негативного отношения к not in кроется в специфике его работы с null-значениями.

Определите результат выполнения следующего запроса:

--Запрос №1
select * from dual
where 1 not in (select 2 from dual union select null from dual) 

Для начала рассмотрим такой запрос:

--Запрос №2
select * from dual
where 2 in (select 2 from dual union select null from dual) 

Ничего необычного в запросе №2 нет: подзапрос возвращает множество из двух строк со значениями «2» и «null», условие where принимает значение true, весь запрос №2 возвращает 1 строку – стандартное поведение.

Теперь рассмотрим разницу в поведении in и not in, здесь нам понадобятся знания о null-арифметике:

1) Любые арифметические операции с null возвращают null

2) Булевые операторы с null работают следующим образом:

  • null AND false = false
  • false AND null = false
  • null AND true = null
  • true AND null = null
  • null OR true = true
  • true OR null = true
  • null OR false = null
  • false OR null = null

Пока все логично. Теперь рассмотрим, как работает IN в запросе №2:
2 IN (2,null) => (2=2) OR (2=null) => true OR null => true
Рассмотрим работу NOT IN в запросе №1:
1 NOT IN (2, null) => (1!=2) AND (1!=null) => true AND null => null

Таким образом, условие where в запросе №1 преобразуется в null, если хотя бы один операнд null, поэтому весь запрос №1 приблизительно эквивалентен следующему запросу:

--Запрос №3
select * from dual
where null=null

Очевидно, что запрос №3 не вернет ни одной строки, соответственно, запрос №1 также не вернет ни одной строки.

Неявное преобразование типов

Тема явного и неявного преобразования типов очень обширна, поэтому, не пытаясь охватить ее в целом, я хотел бы рассмотреть лишь один пример. Пускай сегодня 10.09.11 10:00:00 и Оракл сконфигурирован так, что формат DD.MM.RR распознается по умолчанию, какой из запросов вернет одну строку?

--Запрос №1
select * from dual where sysdate>'10.09.11';
--Запрос №2
select * from dual where sysdate||''='10.09.11'; 

Ответ – оба. Почему так и как это, вообще, возможно? Ответ лежит в механизме неявного преобразования типов.

Рассмотрим запрос №1: в where мы сравниваем дату со строкой, в этом случае Оракл пытается преобразовать строку в дату, если формат строки соответствует одному из форматов даты по умолчанию (формат даты по умолчанию для сессии можно посмотреть в параметре NLS_DATE_FORMAT, выполнив запрос

select * from nls_session_parameters). Если формат строки не отвечает формату даты по умолчанию, то получим ошибку. В нашем случае форматы соответствуют и строка ‘10.09.11’ преобразуется в дату 10.09.11 00:00:00, поскольку sysdate = 10.09.11 10:00:00, то запрос №1 вернет 1 строку.

Рассмотрим запрос №2: в where происходит конкатенация даты со строкой, результатом такой операции будет строка, причем при неявном преобразовании даты в строку происходит урезание данных до формата DD.MM.RR, т.е. мы сравниваем две строки ‘10.09.11’ и ‘10.09.11’. В результате условие where выполняется, и запрос возвращает одну строку.

Заключение

Приведенный обзор не претендует на полноту освещения какой-либо функциональности Oracle, создан «for fun» и призван продемонстрировать несколько случаев нестандартного использования возможностей синтаксиса sql.

Поиск дубликатов MySQL

Сборник запросов для поиска, изменения и удаления дублей в таблице MySQL по одному и нескольким полям. В примерах все запросы будут применятся к следующий таблице:

1

Поиск дубликатов

Подсчет дублей


Запрос подсчитает количество всех записей с одинаковыми значениями в поле `col1`.

SELECT
	`col1`,
	COUNT(`col1`) AS `count`
FROM
	`table`
GROUP BY
	`col1`
HAVING 
	`count` > 1
Результат:

Подсчет дубликатов по нескольким полям:
SELECT
	`col1`,
	`col2`,
	COUNT(*) AS `count`
FROM
	`table`
GROUP BY
	`col1`,`col2`
HAVING 
	`count` > 1
Результат:

Все записи с одинаковыми значениями


Запрос найдет все записи с одинаковыми значениями в `col1`.

SELECT 
	*
FROM 
	`table`
WHERE 
	`col1` IN (SELECT `col1` FROM `table` GROUP BY `col1` HAVING COUNT(*) > 1)
ORDER BY
	`col1`
Результат:

Для одинаковых значений в `col1` и `col2`:

SELECT 
	*
FROM 
	`table`
WHERE 
	`col1` IN (SELECT `col1` FROM `table` GROUP BY `col1` HAVING COUNT(*) > 1)
	AND `col2` IN (SELECT `col2` FROM `table` GROUP BY `col2` HAVING COUNT(*) > 1)
ORDER BY
	`col1`

Получить только дубликаты


Запрос получит только дубликаты, в результат не попадают записи с самым ранним `id`.

SELECT 
	`table`.*
FROM
	`table`
LEFT OUTER JOIN 
	(SELECT MIN(`id`) AS `id`, `col1` FROM `table` GROUP BY `col1`) AS `tmp` 
ON 
	`table`.`id` = `tmp`.`id`  
WHERE
	`tmp`.`id` IS NULL
Результат:

Для нескольких полей:
SELECT 
	`table`.*
FROM
	`table`
LEFT OUTER JOIN 
	(SELECT MIN(`id`) AS `id`, `col1`, `col2` FROM `table` GROUP BY `col1`, `col2`) AS `tmp` 
ON 
	`a`.`id` = `tmp`.`id`  
WHERE
	`tmp`.`id` IS NULL

2

Уникализация записей

Запрос сделает уникальные названия только у дублей, дописав `id` в конец `col1`.

UPDATE  
	`table`
LEFT OUTER JOIN 
	(SELECT MIN(`id`) AS `id`, `col1` FROM `table` GROUP BY `col1`) AS `tmp` 
ON 
	`table`.`id` = `tmp`.`id`
SET
	`table`.`col1` = CONCAT(`table`.`col1`, '-', `table`.`id`)    
WHERE
	`tmp`.`id` IS NULL
Результат:

По нескольким полям:
UPDATE  
	`table`
LEFT OUTER JOIN 
	(SELECT MIN(`id`) AS `id`, `col1`, `col2` FROM `table` GROUP BY `col1`, `col2`) AS `tmp` 
ON 
	`table`.`id` = `tmp`.`id`
SET
	`table`.`col1` = CONCAT(`table`.`col1`, '-', `table`.`id`)    
WHERE
	`tmp`.`id` IS NULL

3

Удаление дубликатов

Удаление дублирующихся записей, останутся только уникальные.

DELETE
	`table`
FROM  
	`table`
LEFT OUTER JOIN 
	(SELECT MIN(`id`) AS `id`, `col1` FROM `table` GROUP BY `col1`) AS `tmp` 
ON 
	`table`.`id` = `tmp`.`id`  
WHERE
	`tmp`.`id` IS NULL
По нескольким полям:
DELETE
	`table`
FROM  
	`table`
LEFT OUTER JOIN 
	(SELECT MIN(`id`) AS `id`, `col1`, `col2` FROM `table` GROUP BY `col1`, `col2`) AS `tmp` 
ON 
	`table`.`id` = `tmp`.`id`  
WHERE
	`tmp`.`id` IS NULL

sql — определяет порядок полей многоколоночного индекса в MySQL Matter

Переполнение стека

  1. Около
  2. Продукты

  3. Для команд
  1. Переполнение стека
    Общественные вопросы и ответы

  2. Переполнение стека для команд
    Где разработчики и технологи делятся частными знаниями с коллегами

  3. Вакансии
    Программирование и связанные с ним технические возможности карьерного роста

  4. Талант
    Нанимайте технических специалистов и создавайте свой бренд работодателя

  5. Реклама
    Обратитесь к разработчикам и технологам со всего мира

  6. О компании

Загрузка…

.

Сортировка данных в SQL, порядок операторов по

При выполнении запроса SELECT строки по умолчанию возвращаются в неопределенном порядке. Фактический порядок строк в этом случае зависит от плана подключения и сканирования, а также от порядка данных на диске, поэтому вы не можете полагаться на него. Оператор ORDER BY используется для организации записей.

Общая структура запроса с оператором ORDER BY

MySQL

  SELECT table_fields FROM list_of_tables
ЗАКАЗАТЬ ПО table_field_1 [ASC | DESC] [, table_field_n [ASC | DESC]]  

В описанной структуре запроса необязательные параметры указаны в квадратных скобках.

  • DESC — сортировка по убыванию
  • ASC (по умолчанию) — сортировка по возрастанию

Сортировка по нескольким столбцам

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

MySQL

  ВЫБРАТЬ Поля_таблиц из списка_таблиц
ORDER BY table_field_1 [ASC | DESC],
поле_таблицы_2 [ASC | DESC];  

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

Правило сортировки применяется только к следующему за ним столбцу.

ORDER BY column_1, column_2 DESC

не то же самое, что

ORDER BY column_1 DESC, column_2 DESC

Примеры

Перечислить названия авиакомпаний в алфавитном порядке из таблицы Company:

MySQL

  SELECT name FROM Company
ЗАКАЗАТЬ ПО имени;  

Сортировка строковых данных осуществляется в лексикографическом (алфавитном) порядке.

Отобразить всю информацию о рейсе, отсортированную по времени вылета самолета в порядке возрастания и по времени прибытия в аэропорт в порядке убывания, из таблицы поездки:

MySQL

  SELECT * FROM Trip
ORDER BY time_out, time_in DESC;  

В этом примере информация сортируется в начале по времени отправления. Затем, если время отправления совпадает, оно сортируется по времени прибытия.

Вывести все данные о покупках, сделанных Хедли Куинси, отсортировав их по убыванию стоимости товаров:

1.Сначала вам нужно узнать идентификатор Хедли Куинси в таблице FamilyMembers:

MySQL

  SELECT member_id от FamilyMembers
ГДЕ member_name = 'Хедли Куинси';  

2. Получите все данные о покупках, сделанных Хедли Куинси, из таблицы Payments:

MySQL

  SELECT * FROM Payments
ГДЕ family_member = (
    ВЫБЕРИТЕ member_id из FamilyMembers
    ГДЕ member_name = 'Хедли Куинси'
);  

3. Отсортируйте полученные данные в порядке убывания стоимости товара:

MySQL

  SELECT * FROM Payments
ГДЕ family_member = (
    ВЫБЕРИТЕ member_id из FamilyMembers
    ГДЕ member_name = 'Хедли Куинси'
) ORDER BY unit_price DESC;  

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *