Какая sql команда используется для упорядочения результатов
Перейти к содержимому

Какая sql команда используется для упорядочения результатов

  • автор:

Логическая обработка запросов: SELECT и ORDER BY

Данная статья завершает серию публикаций о логической обработке запросов. В ней будут описаны последние шаги в логической обработке запросов, связанные с предложениями SELECT и ORDER BY и фильтрами TOP и OFFSET-FETCH.

Логическая обработка запросов определяет концептуальную интерпретацию запросов. Глубокое понимание этой темы — ключевое условие для подготовки корректных и эффективных запросов. В предыдущих статьях серии я представил обзор темы и описал некоторые важнейшие предложения запроса. Мы рассмотрели предложение FROM и табличные операторы, предложение WHERE, а также предложения GROUP BY и HAVING. В первой части (см. Windows IT Pro/RE № 3 за 2016 год) был дан обзор темы, приведена тестовая база данных TSQLV4 (http://tsql.solidq.com/SampleDatabases/TSQLV4.zip) и показаны примеры запросов, которые я назвал простым и сложным.

Полная блок-схема логической обработки запросов

На рисунке показана полная блок-схема для логической обработки запросов, содержащая шаг 5, на котором обрабатывается предложение SELECT, шаг 6, на котором обрабатывается предложение ORDER BY, и шаг 7, на котором применяются фильтры TOP и OFFSET-FETCH.

Полная блок-схема логической обработки запросов
Рисунок. Полная блок-схема логической обработки запросов

Шаг 5, на котором выполняется предложение SELECT, обрабатывает результат шага 4, на котором применяется фильтр HAVING. Его можно разделить на два промежуточных шага: на шаге 5.1 вычисляются выражения в списке SELECT, а на шаге 5.2 обрабатывается предложение DISTINCT, если оно присутствует.

Шаг 6, на котором обрабатывается предложение ORDER BY, принимает в качестве входных данных результат шага 5. Без предложения ORDER BY во внешнем запросе нет гарантии упорядоченности представления результата запроса, так как результат считается реляционным. Поскольку во внешнем запросе имеется предложение ORDER BY, результат считается нереляционным (курсор), и упорядоченность представления гарантируется.

Кроме того, на рисунке показана обработка фильтров TOP и OFFSET-FETCH, которую можно рассматривать как шаг 7. Переключатель TOP фильтрует запрошенное количество или процент строк в указанном порядке, при наличии предложения ORDER BY. Если предложение ORDER BY отсутствует, порядок следует считать произвольным. Для фильтра OFFSET-FETCH необходимо наличие предложения ORDER BY. Он пропускает число строк, указанное в предложении OFFSET, и фильтрует число строк, указанное в предложении FETCH, на основе определенного порядка.

Применим шаги 5, 6 и 7 к нашим тестовым запросам. В статье «Логическая обработка запросов: GROUP BY и HAVING», опубликованной в предыдущем номере, описаны выходные данные шага 4 в обоих тестовых запросах. Напомню, что выходные данные шага 4 используются как входные данные шага 5. В листинге 1 содержится полный простой тестовый запрос.

На экране 1 приводится результат предложения HAVING (как описано в предыдущей статье), который используется как входные данные для шага 5.

Результат предложения HAVING как входные данные для шага 5
Экран 1. Результат предложения HAVING как входные данные для шага 5

Поскольку запрос сгруппированный, строки в результатах шага 4 организованы в группах. На шаге 5 вычисляются выражения из списка SELECT для группы, что приведет к двум строкам для двух групп, а на шаге 6 эти строки упорядочены по numorders. На экране 2 приводится окончательный результат этого запроса.

Окончательный результат простого запроса для шага 5
Экран 2. Окончательный результат простого запроса для шага 5

Предложение ORDER BY появляется во внешнем запросе.

В листинге 2 представлен полный сложный тестовый запрос.

Как выглядит состояние данных перед применением шага 5, показано на экране 3.

Состояние данных перед применением шага 5 для сложного запроса
Экран 3. Состояние данных перед применением шага 5 для сложного запроса

Строки в результатах шага 4 организованы в группы, так как запрос является сгруппированным. На данном этапе у нас пять групп. На шаге 5 вычисляются выражения в списке SELECT, что дает пять строк. Обратите внимание на любопытное сочетание группирования и окон в этом запросе. Выражение SUM (SUM (A.val)) OVER () вычисляет оконный общий итог сгруппированных итоговых значений. В предыдущей статье об этой функции было рассказано подробно.

На шаге 6 определено упорядочение на основе numorders (конкретное число заказов). Переключатель TOP фильтрует первые четыре строки на основе порядка numorders. Также имеется параметр WITH TIES, который включает связи с последней строкой, если они существуют. В данном случае связей с последней строкой нет, поэтому окончательный результат запроса содержит четыре строки, как показано на экране 4.

Окончательный результат сложного запроса
Экран 4. Окончательный результат сложного запроса

Предложение ORDER BY находится во внешнем запросе, поэтому порядок представления гарантирован.

В следующих разделах приводятся дополнительные сведения о шагах 5, 6 и 7.

Обработка предложения SELECT

Как уже отмечалось, на шаге 5 обрабатывается предложение SELECT. Он может быть разделен на два промежуточных шага. На шаге 5.1 вычисляется выражение в списке SELECT, а на шаге 5.2 обрабатывается предложение DISTINCT.

Шаг 5.1. Вычисление выражений

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

В реляционной модели заголовок отношения представляет собой набор атрибутов. Поскольку набор не упорядочен и не имеет дубликатов, атрибут идентифицируется по имени, а не по порядковому номеру. Кроме того, вы не можете дублировать имена атрибутов. В зависимости от контекста это условие не всегда действует в T-SQL (то же относится к SQL). Например, T-SQL позволяет запросу создать неименованный столбец, который является результатом вычислений, как показано в листинге 3.

Этот запрос формирует данные, показанные на экране 5.

Результат выполнения запроса с неименованным столбцом
Экран 5. Результат выполнения запроса с неименованным столбцом

Однако T-SQL применяет оба требования, если вы попытаетесь определить табличное выражение, такое как производная таблица, обобщенные табличные выражения (CTE), представление или встроенная функция, возвращающая табличное значение, на основе запроса. Например, программный код в листинге 4 выдаст ошибку.

Попытка создать это представление заканчивается неудачей.

Чтобы исправить ошибку, убедитесь, что имена назначены всем столбцам и что имена всех столбцов уникальны (см. листинг 5).

На этот раз представление будет построено успешно.

Выполните следующую команду для очистки:

DROP VIEW dbo.CustOrders;

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

Если вы попытаетесь выполнить этот запрос, будет получена ошибка, как показано на экране 6.

Ошибка при выполнении листинга 6
Экран 6. Ошибка при выполнении листинга 6

Чтобы сделать псевдоним, созданный одним из вычислений, доступным другому вычислению, необходимо определить псевдоним на шаге, предшествующем тому, на котором он применяется. Например, можно создать псевдоним с использованием оператора CROSS APPLY и задействовать его во втором операторе CROSS APPLY. Затем вы можете использовать результаты первого и второго операторов на всех последующих шагах, в том числе WHERE, GROUP BY, HAVING и SELECT. В листинге 7 приведен программный код, в котором реализован этот метод.

Другая важная особенность шага 5.1, о которой следует помнить, состоит в том, что на данном шаге вычисляется оконная функция. Она должна работать с набором результатов базового запроса (перед удалением дубликатов), и набор результатов базового запроса формируется, когда вы добираетесь до шага 5. До этого шага результат запроса только формируется. Не разрешается использовать оконные функции непосредственно на предыдущих шагах логической обработки запросов. Это означает, что если вам нужно воспользоваться оконной функцией на любом шаге, предшествующем шагу 5, делать это необходимо с помощью табличного выражения. Например, если вы хотите фильтровать позиции заказов в строках с номерами 21-30 по orderid, вам не удастся напрямую обратиться к оконной функции ROW_NUMBER в предложении WHERE; сделать это нужно косвенно с помощью табличного выражения (см. листинг 8).

Внутренний запрос вычисляет номера строк в предложении SELECT и назначает результирующему столбцу псевдоним rownum. Затем внешний запрос ссылается на псевдоним rownum в предложении WHERE.

Кстати, вы не можете использовать этот прием с оператором CROSS APPLY и предложением VALUES для назначения псевдонимов вычислениям на основе оконных функций. Дело в том, что оператор APPLY показывает на правой стороне только одну строку слева, а оконные функции должны увидеть результат запроса целиком. Поэтому при использовании оконных функций необходимо избрать более длинный путь с полным табличным выражением, как в последнем примере.

Шаг 5.2. Обработка предложения DISTINCT

Если в предложении SELECT присутствует предложение DISTINCT, то на шаге 5.2 удаляются дубликаты из результатов шага 5.1. Примечательно, что по реляционной теории тело отношения представляет собой набор и потому не может иметь дубликатов. Поэтому, например, запрос, который проецирует только атрибут страны на отношение Employee, должен возвращать конкретные страны, в которых находятся сотрудники. T-SQL, как и SQL, отклоняется от реляционной модели и допускает дубликаты в таблице. Реляционная модель отчасти основывается на теории множеств, а T-SQL — на теории мультимножеств. Мультимножество похоже на множество в том смысле, что оно не упорядочено, но отличается от множества тем, что допускает дубликаты. В частности, вы можете создать таблицу без ключа и таким образом разрешить дублированные строки. А запрос, возвращающий подмножество столбцов, может возвращать дубликаты. Рассмотрим следующий запрос:

SELECT country FROM HR.Employees;

В таблице девять сотрудников, и потому запрос возвращает девять строк с дублированными странами (см. экран 7).

Строки с дублированными данными
Экран 7. Строки с дублированными данными

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

SELECT DISTINCT country FROM HR.Employees;

Этот запрос возвращает только две страны, как показано на экране 8.

Дубликаты убраны
Экран 8. Дубликаты убраны

Напомню, что это предложение DISTINCT обработано на шаге 5.2 и применяется после вычисления всех выражений на шаге 5.1. Это означает, что при наличии оконных функций они вычисляются до того, как применяется DISTINCT. В качестве примера попытайтесь определить, сколько строк будет возвращено запросом, приведенным в листинге 9, прежде чем выполнить его.

Если вы предположили, что две, то вы ошиблись. Перед применением шага 5.1 во входной таблице насчитывается 9 строк. Это означает, что функция ROW_NUMBER формирует 9 отдельных номеров строк в этих 9 строках. Дубликаты, которые могли бы быть удалены предложением DISTINCT, отсутствуют, и вы получаете выходные данные, как показано на экране 9.

Результат использования предложения DISTINCT с оконной функцией
Экран 9. Результат использования предложения DISTINCT с оконной функцией

Но что если требуется вычислить номера строк для конкретных стран? Один вариант — подготовить запрос, который возвращает только уникальные страны, определить табличное выражение на основе этого запроса, а затем использовать внешний запрос для вычисления номеров строк для уникальных стран. В листинге 10 приводится полный запрос.

Этот запрос формирует выходные данные, как на экране 10.

Результат вычисления номера строк для конкретных стран
Экран 10. Результат вычисления номера строк для конкретных стран

Другой вариант — использовать GROUP BY вместо DISTINCT. Помните, что предложение GROUP BY обрабатывается на шаге 3, намного раньше шага 5, на котором обрабатывается предложение SELECT. Это означает, что любые оконные функции применяются на шаге 5.1, после группирования. В листинге 11 приводится полный запрос.

В результатах содержится две строки с двумя уникальными странами и соответствующими им номерами строк.

Обработка предложения ORDER BY

Без предложения ORDER BY в запросе результат считается реляционным, поэтому данные могут следовать в разном порядке. Если требуется обеспечить порядок представления результатов для таких целей, как подготовка отчетов, необходимо ввести во внешний запрос предложение ORDER BY.

Предложение ORDER BY обрабатывается на шаге 6, после предложения SELECT, которое обрабатывается на шаге 5, поэтому разрешается ссылаться на псевдонимы, которые были созданы в предложении SELECT, в предложении ORDER BY. Это можно увидеть как в простом тестовом запросе, так и в сложном. Предложение SELECT подсчитывает число заказов, обозначая его псевдонимом numorders, а затем предложение ORDER BY ссылается на псевдоним numorders.

Обычно разрешается в предложении ORDER BY ссылаться на выражения, даже если они не появляются в предложении SELECT. Другими словами, можно выполнять упорядочение по величинам, которые вы не обязательно хотите возвращать. Однако, как правило, делать это разрешается при условии, что выражение было бы действительным, если бы было указано в предложении SELECT. Правила строже, если используется предложение DISTINCT. В этом случае предложение ORDER BY ограничено только выражениями, которые появляются в предложении SELECT. Например, запрос в листинге 12 неверен.

Такое ограничение основано на том, что одно уникальное значение может представлять несколько исходных строк, а выражение в предложении ORDER BY может иметь различные результаты для разных исходных строк, связанных с одной целевой строкой. Например, представьте себе запрос, который возвращает конкретные страны и заказы по идентификатору сотрудника. С одной страной может быть связано несколько различных идентификаторов. Поэтому T-SQL просто не поддерживает такие запросы. Но что если существует соответствие «один к одному» между результатами выражений SELECT и ORDER BY, как в листинге 12? Можно применить DISTINCT без упорядочения в одном запросе, определить табличное выражение на основе этого запроса, а затем выполнить упорядочение во внешнем запросе (см. листинг 13).

Этот запрос формирует выходные данные, показанные в сокращенном виде на экране 11.

Результаты использования обходного приема
Экран 11. Результаты использования обходного приема

ORDER BY, табличные выражения, TOP и OFFSET-FETCH

Если вы хотите определить табличное выражение, такое как производная таблица, обобщенные табличные выражения (CTE), представление или встроенная функция, возвращающая табличное значение, внутреннему запросу не разрешается иметь предложение ORDER BY. Поэтому предполагается, что табличное выражение представляет собой отношение, и результат запроса с предложением ORDER BY не является реляционным. Например, попытка создать представление в листинге 14 неверна.

Если вы выполните программный код листинга 14, то будет получена ошибка, как на экране 12.

Ошибка при выполнении листинга 14
Экран 12. Ошибка при выполнении листинга 14

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

Если вы внимательно прочитаете сообщение об ошибке, то заметите, что требование отсутствия ORDER BY во внутреннем запросе снимается в исключительных случаях, например когда указаны фильтры OFFSET-FETCH или TOP. Эти фильтры применяются к результату шага 5.2 и полагаются на предложение ORDER BY, как будто оно часть спецификации фильтра. Теоретически эти фильтры могли быть спроектированы с собственными спецификациями упорядочения, которые не следует путать с порядком представления. Но, к сожалению, в действительности это не так. Поэтому, когда вы используете эти фильтры во внутреннем запросе, разрешается добавить предложение ORDER BY для поддержки фильтра. Например, действительно определение представления, как в листинге 15.

Однако необходимо помнить правило, упомянутое мною в связи с порядком представления: он гарантируется только в том случае, если внешний запрос располагает предложением ORDER BY. Например, рассмотрим следующий запрос:

SELECT * FROM Sales.MyView;

Вы гарантированно получаете три заказа с высшими значениями, но, поскольку внешний запрос не имеет предложения ORDER BY, строки не обязательно следуют в каком-то определенном порядке. Есть вероятность, что строки будут упорядочены, так как SQL Server использует алгоритм с упорядочением для обработки TOP и OFFSET-FETCH, чтобы выяснить, какие строки следует фильтровать. Порядок строк не перестраивается просто ради того, чтобы представить строки сортированными, так как для этого потребуется больше усилий. Любой порядок строк в выходных данных считается приемлемым. Поэтому, выполнив этот запрос на своем компьютере, я получил выходные данные, в которых строки, похоже, были упорядочены по убыванию значений (см. экран 13).

Пример выходных данных с упорядочением вследствие оптимизации
Экран 13. Пример выходных данных с упорядочением вследствие оптимизации

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

Распространенная ошибка — попытаться создать «сортированное представление», применив фильтр TOP (100) PERCENT и предложение ORDER BY во внутреннем запросе (см. листинг 16).

Эта попытка неверна, поскольку, как уже отмечалось, представление является отношением и поэтому не может быть упорядоченным. Кроме того, когда SQL Server оптимизирует запрос для представления, выясняется, что комбинация TOP (100) PERCENT и ORDER BY во внутреннем запросе бессмысленна, и исключает ее. Например, выполните следующий запрос:

SELECT * FROM Sales.MyView;

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

Сокращенный вариант выходных данных с интеллектуальной оптимизацией
Экран 14. Сокращенный вариант выходных данных с интеллектуальной оптимизацией

Как можно заметить, строки не сортированы по значениям в порядке убывания. Это не ошибка, а интеллектуальная оптимизация. Как уже отмечалось, единственный способ гарантировать порядок представления — задействовать предложение ORDER BY во внешнем запросе.

Если вы сочетаете использование оконных функций и фильтра TOP или OFFSET-FETCH в одном запросе, помните, что оконные функции применяются на шаге 5.1 перед фильтрами TOP и OFFSET-FETCH, но не наоборот. Рассмотрим пример в листинге 17.

Функция ROW_NUMBER нумерует строки, а оконная функция COUNT (*) подсчитывает их перед применением фильтра OFFSET-FETCH. На экране 15 показано, как выглядят выходные данные этого запроса.

Выходные данные запроса в листинге 17
Экран 15. Выходные данные запроса в листинге 17

Обратите внимание, что результат состоит из строк с номерами от 21 до 30, а не от 1 до 10, а столбец totalrows содержит значение 830, а не 10. Если так и требовалось, это хорошо. Однако, если нужно применить оконные функции к результату фильтра TOP или OFFSET-FETCH, используйте табличное выражение на основе запроса, который применяет фильтр, а затем используйте оконные функции во внешнем запросе.

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

Листинг 1. Простой тестовый запрос

USE TSQLV4; -- http://tsql.solidq.com/SampleDatabases/TSQLV4.zip SELECT C.custid, COUNT( O.orderid ) AS numorders FROM Sales.Customers AS C LEFT OUTER JOIN Sales.Orders AS O ON C.custid = O.custid WHERE C.country = N'Spain' GROUP BY C.custid HAVING COUNT( O.orderid ) 
Листинг 2. Сложный тестовый запрос
SELECT TOP (4) WITH TIES C.custid, A.custlocation, COUNT( DISTINCT O.orderid ) AS numorders, SUM( A.val ) AS totalval, SUM( A.val ) / SUM( SUM( A.val ) ) OVER() AS pct FROM Sales.Customers AS C LEFT OUTER JOIN ( Sales.Orders AS O INNER JOIN Sales.OrderDetails AS OD ON O.orderid = OD.orderid AND O.orderdate >= '20160101' ) ON C.custid = O.custid CROSS APPLY ( VALUES( CONCAT(C.country, N'.' + C.region, N'.' + C.city), OD.qty * OD.unitprice * (1 - OD.discount) ) ) AS A(custlocation, val) WHERE A.custlocation IN (N'Spain.Madrid', N'France.Paris', N'USA.WA.Seattle') GROUP BY C.custid, A.custlocation HAVING COUNT( DISTINCT O.orderid ) 
Листинг 3. Создание неименованного столбца в запросе
SELECT C.custid, O.custid, O.orderid, YEAR(O.orderdate) FROM Sales.Customers AS C LEFT OUTER JOIN Sales.Orders AS O ON C.custid = O.custid;

Листинг 4. Запрос с табличным выражением

CREATE VIEW dbo.CustOrders AS SELECT C.custid, O.custid, O.orderid, YEAR(O.orderdate) FROM Sales.Customers AS C LEFT OUTER JOIN Sales.Orders AS O ON C.custid = O.custid; GO

Листинг 5. Запрос с проверкой имен столбцов

CREATE VIEW dbo.CustOrders AS SELECT C.custid AS ccustid, O.custid AS ocustid, O.orderid, YEAR(O.orderdate) AS orderyear FROM Sales.Customers AS C LEFT OUTER JOIN Sales.Orders AS O ON C.custid = O.custid; GO

Листинг 6. Попытка использования псевдонима для вычисления в предложении SELECT

SELECT orderid, YEAR(Orderdate) AS orderyear, DATEFROMPARTS(orderyear, 12, 31) AS endofyear FROM Sales.Orders;

Листинг 7. Создание псевдонима

SELECT orderid, orderyear, endofyear FROM Sales.Orders CROSS APPLY ( VALUES( YEAR(Orderdate) ) ) AS A1(orderyear) CROSS APPLY ( VALUES( DATEFROMPARTS(orderyear, 12, 31) ) ) AS A2(endofyear);

Листинг 8. Использование табличного выражения для оконной функции

WITH C AS ( SELECT orderid, orderdate, custid, empid, ROW_NUMBER() OVER(ORDER BY orderid) AS rownum FROM Sales.Orders ) SELECT orderid, orderdate, custid, empid FROM C WHERE rownum BETWEEN 21 AND 30;

Листинг 9. Пример использования предложения DISTINCT с оконной функцией

SELECT DISTINCT country, ROW_NUMBER() OVER(ORDER BY country) AS rownum FROM HR.Employees;

Листинг 10. Вычисление номера строк для конкретных стран

WITH C AS ( SELECT DISTINCT country FROM HR.Employees ) SELECT country, ROW_NUMBER() OVER(ORDER BY country) AS rownum FROM C;

Листинг 11. Пример использования GROUP BY вместо DISTINCT

SELECT country, ROW_NUMBER() OVER(ORDER BY country) AS rownum FROM HR.Employees GROUP BY country;

Листинг 12. Неправильное использование выражений с ORDER BY

SELECT DISTINCT QUOTENAME(CONCAT(MONTH(orderdate), ‘/’, YEAR(orderdate))) AS monthyear FROM Sales.Orders ORDER BY YEAR(orderdate), MONTH(orderdate);

Листинг 13. Обходной прием

WITH C AS ( SELECT DISTINCT MONTH(orderdate) AS ordermonth, YEAR(orderdate) AS orderyear FROM Sales.Orders ) SELECT QUOTENAME(CONCAT(ordermonth, ‘/’, orderyear)) AS monthyear FROM CORDER BY orderyear, ordermonth;

Листинг 14. Неверная попытка создать представление

CREATE VIEW Sales.MyView AS SELECT orderid, val FROM Sales.Ordervalues ORDER BY val DESC; GO

Листинг 15. Действительное определение представления с ORDER BY

CREATE VIEW Sales.MyView AS SELECT TOP (3) orderid, val FROM Sales.Ordervalues ORDER BY val DESC; GO

Листинг 16. Попытка создать «сортированное представление» с TOP (100) PERCENT и ORDER BY

ALTER VIEW Sales.MyView AS SELECT TOP (100) PERCENT orderid, val FROM Sales.Ordervalues ORDER BY val DESC; GO

Листинг 17. Использование оконных функций и фильтра TOP или OFFSET-FETCH в одном запросе

SELECT orderid, orderdate, custid, empid, ROW_NUMBER() OVER(ORDER BY orderdate, orderid) AS rownum, COUNT(*) OVER() AS totalrows FROM Sales.Orders ORDER BY orderdate, orderid OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

SQL SELECT

Команда SELECT (SQL запрос) производит выборку данных из таблиц по запросу. Язык SQL допускает три типа синтаксических конструкций, начинающихся с ключевого слова SELECT:

  1. оператор выборки (select statement)
  2. спецификация курсора (cursor specification)
  3. подзапрос (subquery).

Синтаксис команды SELECT в MySQL

Основные ключевые слова и параметры команды SELECT в MySQL

  • DISTINCT — возвращает только одно значение для каждого набора одинаковых выбранных значений столбца
  • ALL — возвращает все выбранные строки, включая все повторяющиеся значения столбцов (принимается по умолчанию)
  • * — выбирает все столбцы из всех таблиц или представлений, перечисленных после оператора FROM
  • schema — идентификатор полномочий, обычно совпадающий с именем некоторого пользователя
  • table.* view.* - выбирает все столбцы из указанной таблицы, представления
  • Expr — извлекает из таблицы (представления) некоторое определяемое выражение
  • table view — имя таблицы(представления), из которой происходит выборка данных.
  • subquery — подзапрос, который сервер обрабатывает тем же самым способом как представление.
  • WHERE — ограничивает множество строк выборкой тех записей, для которых условие является истинным; если это предложение опускается, сервер возвращает все строки из таблиц.
  • GROUP BY — группирует выбранные строки по группам строк с одинаковым значением указанных полей и возвращает одиночную строку итоговой информации для каждой группы.
  • HAVING — ограничивает выбираемые группы строк такими группами, для которых определяемое условие является истинным; если это предложение опускается, сервер возвращает строки всех групп.
  • UNION UNION ALL INTERSECT MINUS — объединяет строки, возвращенные двумя утверждениями SELECT с использованием операции пересечения множеств; для ссылки на столбец вводится псевдоним для его обозначения; предложение FOR UPDATE не может использоваться с этими операторами
  • ORDER BY — упорядочивает строки, возвращенные запросом.
  • Expr— значение выражения определяет правило упорядочивания строк.
  • ASC DESC — определяет порядок вывода данных (по возрастанию или по убыванию); значением по умолчанию является ASC.
  • FOR UPDATE — блокирует выбранные строки.
  • OF — блокирует выбираемые строки для специфической таблицы в объединении.
  • NOWAIT — возвращает управление пользователю, если команда SELECT пытается блокировать строку, которая уже блокирована другим пользователем; если это предложение опускается, сервер ждет, пока строка не станет доступной и только тогда возвращает результаты команды SELECT.

Синтаксис команды SELECT в Oracle

Основные ключевые слова и параметры команды SELECT в Oracle

  • DISTINCT — возвращает только одно значение для каждого набора одинаковых выбранных значений столбца.
  • ALL — возвращает все выбранные строки в Oracle, включая все повторяющиеся значения столбцов (принимается по умолчанию).
  • * — выбирает все столбцы из всех таблиц или представлений, перечисленных после раздела FROM.
  • schema — идентификатор полномочий, обычно совпадающий с именем некоторого пользователя.
  • table.* view.* - выбирает все столбцы из указанной таблицы Oracle, представления.
  • Expr — извлекает из таблицы (представления) некоторое определяемое выражение.
  • table view — имя таблицы(представления), из которой происходит выборка данных.
  • c_alias – алиасное имя (псевдоним) извлекаемого столбца, выражения.
  • t_alias – алиасное имя (псевдоним) таблицы Oracle.
  • subquery — подзапрос, который сервер обрабатывает тем же самым способом как представление.
  • WHERE — ограничивает множество строк выборкой тех записей, для которых условие является истинным; если это предложение опускается, сервер возвращает все строки из таблиц Oracle.
  • GROUP BY — группирует выбранные строки по группам строк с одинаковым значением указанных полей и возвращает одиночную строку итоговой информации для каждой группы.
  • HAVING — ограничивает выбираемые группы строк такими группами, для которых определяемое условие является истинным; если это предложение опускается, сервер возвращает строки всех групп.
  • UNION [ALL] INTERSECT MINUS — объединяет строки, возвращенные двумя утверждениями SELECT с использованием операции пересечения множеств; для ссылки на столбец вводится псевдоним для его обозначения. Предложение FOR UPDATE не может использоваться с этими операторами.
  • ORDER BY — упорядочивает строки, возвращенные запросом: в Expr — указывается значение выражения, которое определяет правило упорядочивания строк по возрастанию ASC или убыванию DESC. Значением по умолчанию является ASC.
  • PARTITION — в отличие от ORDER BY позволяет частично упорядочивать набор данных.
  • FOR UPDATE - блокирует выбранные строки.
  • NOWAIT - возвращает управление пользователю, если команда SELECT пытается блокировать строку, которая уже блокирована другим пользователем; если это предложение опускается, сервер ждет, пока строка не станет доступной и только тогда возвращает результаты команды SELECT.

Описание команды SELECT

Основой всех синтаксических конструкций, начинающихся с ключевого слова SELECT, является синтаксическая конструкция “табличное выражение”. Семантика табличного выражения состоит в том, что на основе последовательного применения разделов FROM, WHERE, GROUP BY и HAVING из заданных в разделе FROM таблиц строится некоторая новая результирующая таблица, порядок следования строк которой не определен и среди строк которой могут находиться дубликаты (т.е. в общем случае таблица-результат табличного выражения является мультимножеством строк).

Наиболее общей является конструкция “спецификация курсора”.

Курсор — это понятие языка SQL, позволяющее с помощью набора специальных операторов получить построчный доступ к результату запроса к БД. К табличным выражениям, участвующим в спецификации курсора, не предъявляются какие- либо ограничения. При определении спецификации курсора используются три дополнительных конструкции: спецификация запроса, выражение запросов и раздел ORDER BY.

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

Выражение запросов — это выражение, строящееся по указанным синтаксическим правилам на основе спецификаций запросов. Единственной операцией, которую разрешается использовать в выражениях запросов, является операция UNION (объединение таблиц) с возможной разновидностью UNION ALL.

Оператор выборки — это отдельный оператор языка SQL, позволяющий получить результат запроса в прикладной программе без привлечения курсора. Поэтому оператор выборки имеет синтаксис, отличающийся от синтаксиса спецификации курсора, и при его выполнении возникают ограничения на результат табличного выражения. Фактически, и то, и другое диктуется спецификой оператора выборки как одиночного оператора SQL: при его выполнении результат должен быть помещен в переменные прикладной программы. Поэтому в операторе появляется раздел INTO, содержащий список переменных прикладной программы, и возникает то ограничение, что результирующая таблица должна содержать не более одной строки. В диалекте SQL СУБД Oracle поддерживается расширенный вариант оператора выборки, результатом которого не обязательно является таблица из одной строки. Такое расширение не поддерживается ни в SQL/89, ни в SQL/92.

Подзапросзапрос, который может входить в предикат условия выборки оператора SQL.

Кстати, данную статью Вы можете найти в интернете по запросам:

Команда SELECT, Синтаксис команды SELECT, Описание команды SELECT.

Какая sql команда используется для упорядочения результатов

Команда UNION просто объединяет вывод нескольких запросов в один. Например, приведенный ниже запрос выводит всех агентов и заказчиков, размещенных в :

SELECT snum, sname FROM Salespeople WHERE city = 'Москва' UNION SELECT cnum, cname FROM Customers WHERE city = 'Москва'
snum sname ----- ------------------ 2001 ТОО Рога и копыта 1001 Иванов
  • число и порядок следования колонок должны быть одинаковы во всех запросах
  • типы данных должны быть совместимы

Совместимость типов определяется просто:

Тип данных колонки Тип результата
Обе колонки типа char с фиксированными длинами L1 и L2 char с длиной равной наибольшему из L1 и L2
Обе колонки типа binary c фиксированной длиной L1 и L2 binary с длиной равной наибольшему из L1 и L2
Одна или обе типа varchar varchar с длиной равной наибольшему из L1 и L2
Одна или обе типа varbinary varbinary с длиной равной наибольшему из L1 и L2
Обе числового типа (smallint,money, float) Тип данных с наибольшей точностью (int=>float)

UNION автоматически исключает дубликаты строк из вывода. Если вы хотите, чтобы все строки из запросов попали в результат используйте UNION ALL:

SELECT snum, city FROM Customers UNION ALL SELECT snum, city FROM Salespeople
snum city ----- ----------- 1001 Москва 1003 Одесса 1002 Рязань 1002 Бобруйск 1001 Лондон 1004 ТОМСК 1007 Караганда 1001 Москва 1002 Хабаровск 1003 Караганда 1004 Сочи 1007 Красноярск

Вместе с UNION может использоваться ORDER BY для упорядочивания вывода. При этом ORDER BY указывается только после последнего запроса, входящего в UNION.

SELECT a.snum, sname, onum, 'Наибольший на ',odate FROM Salespeople a, Orders b WHERE a.snum = b.snum AND b.amt = ( SELECT MAX(amt) FROM Orders c WHERE c.odate = b.odate ) UNION SELECT a.snum, sname, onum, 'Наименьший на ', odate FROM Salespeople a, Orders b WHERE a.snum = b.snum AND b.amt = ( SELECT MIN(amt) FROM Orders c WHERE c.odate = b.odate ) ORDER BY 3
snum sname onum odate ----- ------- ----- -------------- ----------- 1007 Шилин 3001 Наименьший на 1999-10-03 1002 Петров 3005 Наибольший на 1999-10-03 1002 Петров 3007 Наименьший на 1999-10-04 1001 Иванов 3008 Наименьший на 1999-10-05 1001 Иванов 3008 Наибольший на 1999-10-05 1003 Егоров 3009 Наибольший на 1999-10-04 1002 Петров 3010 Наименьший на 1999-10-06 1001 Иванов 3011 Наибольший на 1999-10-06

3 - просто номер колонки вывода. Так проще сортировать записи, т.к. при использовании UNION имена колонок могут выглядеть как угодно.

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

Этим заканчиваются шаги о запросах. Далее нам предстоит узнать о том, как данные вводятся в таблицы и как создаются собственно таблицы и все, что с этим связано. Запросы будут постоянно встречаться в других типах команд. Следующие шаги будут посвящены: командам вставки, обновления и удаления записей.

9.2. Оператор выборки данных select, использование условий поиска, сортировка результатов запроса. Синтаксис оператора select.

Запросы - это наиболее часто используемый момент в SQL, ведь этот язык для них и был создан. Запрос представляет собой некую команду, которая обращается к БД и сообщает ей, чтобы она отобразила определенную информацию из таблиц в память. Эта информация обычно выводится непосредственно на экран компьютера, терминал, посылается принтеру, сохраняется в файле или служит исходными данными для другой команды или запроса. Все запросы в SQL состоят из одиночной команды SELECT с достаточно простой структурой, однако путем ее использования можно выполнить сложную обработку данных. В самой простой форме, команда SELECT просто обращается к БД. чтобы извлечь информацию из таблицы. Например, можно вывести таблицу студентов, дав следующий запрос: SELECT SNUM, SFAM, SIMA, SOTCH, STIP FROM STUDENTS; Большинство программ, работающих с языком SQL. выдают заголовки полей, поэтому в дальнейшем результаты будут приводиться именно в такой форме. Детально поясним каждую часть этой команды: SELECT - ключевое слово, которое сообщает БД. что эта команда является запросом, т.е. все запросы начинаются этим словом. SNUM, SFAM, SIMA, SOTCH, STIP - список полей из таблицы, которые выбираются запросом. Поля. не перечисленные здесь, не будут включены в вывод команды. FROM STUDENTS - ключевое слово, подобно SELECT, которое должно быть представлено в каждом запросе. STUDENTS-таблица, источник информации. Точка с запятой (;) используется во всех интерактивных командах SQL для сообщения БД. что команда заполнена и готова выполниться. Если необходимо получить каждое поле таблицы, имеется не╜обязательное сокращение в виде символа "звездочка" (*), которое можно использовать для вывода полного списка полей следующим образом: SELECT * FROM STUDENTS; Команда SELECT способна извлечь строго определенную информацию из таблицы. Например, при необходимости вывода только определенных полей таблицы, просто из списка исключа╜ются не нужные поля. Например, запрос Этот способ позволяет работать с большими таблицами, содержащих данные, не нужные в данный момент пользователю. При работе с данными очень часто возникает потребность в удалении избыточных данных. Это реализуется с использованием DISTINCT - аргумент, который обеспечивает возможность уст╜ранять повторяющиеся значения из предложения SELECT. Например, необходимо узнать, какие студенты в на╜стоящее время сдавали учебные предметы, причем не требуется уточнение полученной оценки и сдаваемого предмета. Запрос SELECT SNUM FROM USP; предоставит вывод, возможно в котором есть записи - дубликаты: Для получения списка результатов без дубликатов в данном случае целесообразно воспользоваться следующим: SELECT DISTINCT SNUM FROM USP; Иначе, DISTINCT просматривает значения, которые были выведены ранее, и не дает им дублироваться в списке. Использование условий поиска для отбора строк. Со временем таблицы становятся очень большими, т.к. увеличивается кол-во добавляемых в них записей. Обычно из всех записей интересуют только определенные, поэтому SQL дает возможность устанавливать критерии выбора записей для вывода. WHERE - предложение команды SELECT, которое позволяет устанавливать предикаты, условие которых может быть или верным или неверным для любой записи таблицы. Команда извлекает только те записи из таблицы, для которой такое утверждение истинно. Предположим, что необходимо выбрать фамилии и размеры стипендии студентов, при этом интересуют только такие, которые получают стипендию в размере 25.50. Такой запрос будет иметь вид: SELECT SPAM, STIP FROM STUDENTS WHERE STIP=25.50; Когда WHERE имеет место, СУБД просматривает всю таблицу по одной записи, чтобы определить, является ли предикат истинным Предложение WHERE совместимо с уже рассмотренными фразами, используемыми в SELECT, т.е. можно использовать наименования полей, устранять дубликаты, или переупорядочивать поля. Но допускается изменять порядок столбцов для имен только в предложении SELECT, но не в предложении WHERE. Таким образом, существует несколько способов заставить таблицу предоставлять ту информацию, которая необходима пользователю, а не просто выводить все ее содержание. Наиболее важно и то, что можно устанавливать предикат, определяющий наличие вывода указанной строки таблицы. Предикаты могут становиться очень сложными, предоставляя высокую точность в решении, какие строки выбирать с помощью запроса. Вообще говоря, часто в предикатах требуется не только оценивать равенство оператора как истинного или ложного, но и осуществлять другие виды связей. Это реализуется с помощью булевых операторов и знаков отношения, причем предикат может содержать неограниченное число условий. В целом, реляционный оператор - это математический символ, который указывает на определенный тип сравнения между двумя значениями, при этом SQL располагает следующим их набором: = равный чему-либо; > больше чем; < меньше чем; >= больше чем или равно; не равно. Эти операторы имеют стандартные значения для числовых данных, а для символьных их определение зависит от кодов АSCII символов - они следуют в алфавитном порядке, причем заглавные буквы имеют меньший код, чем строчные, поэтому, например, "Z" < "а". Предположим, что необходимо вывести список студентов, получающих стипендию, т.е. для которых STIP>0. Для этого воспользуемся следующим запросом: SELECT * FROM STUDENTS WHERE STIP > 0; Стандартными булевыми операторами, которые используются в SQL, являются AND, OR и NOT. Напомним, как они работают: ∙AND использует два операнда в форме A AND В и оцени╜вает их по отношению к истине: верны ли они оба; ∙OR использует два операнда в форме A OR В и оценивает на истинность: верен ли один из них; ∙NOT использует один операнд в форме NOT А и заменяет его значение с ИСТИНА на ЛОЖЬ, или наоборот. Связывая предикаты с булевскими операторами, можно значительно увеличить возможности выборки данных. Например, по таблице с данными об успеваемости можно получить информацию о всех студентах, сдавших предмет с кодом 2003: SELECT * FROM USP WHERE OCENKA >=3 AND PNUM = 2003; Если в аналогичном запросе использовать OR, то будет получена информация обо всех студентах, имеющих оценки 3 и выше, или сдававших (независимо от оценки) учебный предмет с кодом 2003: SELECT * FROM USP WHERE OCENKA >=3 OR PNUM = 2003; Условие NOT может использоваться для инвертирования логических значений. Например, для вывода информации о студентах. у которых оценки не являются 3, можно воспользоваться следующим запросом: SELECT * FROM USP WHERE NOT (OCENKA = 3) ; Булевский оператор помещается перед реляционным оператором, на который он действует, а при необходимости расширения действия используются скобки. На╜пример, для вывода информации о студентах, у которых оценки не являются 3 и в то же время по учебному предмету с кодом, не равным 2005, можно воспользоваться таким запросом: SELECT * FROM USP WHERE NOT (OCENKA = 3 AND PNUM = 2005) ; В предложении SELECT в дополнение к традиционным реляционным и булевским операторам, рассмотренным выше, могут быть использованы специальные операторы IN, BETWEEN, LIKE, и IS NULL. Оператор IN определяет набор значений, в который данное значение должно быть включено. Например, если в соответствии с учебной БД возникает необходимость в выводе информации обо всех студентах, имя которых Анатолий или Владимир, нужно использовать следующий запрос: SELECT * FROM STUDENTS WHERE SIMA = 'Анатолий' OR SIMA = 'Владимир'; Оператор BETWEEN несколько похож на IN, но, в отличие от определения из набора. BETWEEN определяет диапазон значений, в который должны умещаться искомые значения, что и делает предикат верным. Структура оператора BETWEEN следующая: вводится начальное значение, ключевое слово AND и конечное значение Следующий пример будет извлекать из таблицы успеваемости номера и оценки всех студентов, оценки которых заключены между 3 и 5: SELECT SNUM, OCENKA FROM USP WHERE OCENKA BETWEEN 3 AND 5; BETWEEN может работать с символьными полями в эквивалентах ASCII, что означает возможность использования BETWEEN для выбора фрагмента из упорядоченных по алфавиту значений. Для примера приведем запрос, выбирающий всех студентов, чьи фамилии попали в определенный алфавитный диапазон: SELECT SFAM, SIMA, SOTCH FROM STUDENTS WHERE SFAM BETWEEN 'К' AND 'С' ; Оператор LIKE применим только к полям типа CHAR или VARCHAR, в которых он ищет подстроки, т.е. он ищет символы и проверяет, совпадают ли они с условием. В качестве условия оператор использует групповые символы - специальные символы, которые соответствуют чему-либо. Существует два типа групповых символов, используемых с LIKE: ∙- символ подчеркивания замещает любой одиночный символ, например, 'М_Л' будет соответствовать словам 'МОЛ' или 'МЕЛ', но не будет соответствовать 'МЕТАЛЛ': ∙- знак процента замещает последовательность любого числа символов, в том числе нулевой длины. Например, '%М%Л' будет соответствовать словам 'МЕЛ' или 'ПОМОЛ', но не соответствует 'МОЛОКО'. В качестве примера найдем всех преподавателей, чьи фамилии начинаются с буквы К: SELECT TFAM, TIMA, ТОТСН FROM TEACHERS WHERE TFAM LIKE 'K%'; Оператор LIKE может быть полезен, например, при поиске значения, если точное его написание неизвестно. Групповой символ % в конце строки необходим в большинстве случаев, если длина оцениваемой строки неизвестна или длина поля больше, чем число символов в оцениваемой строке. Сортировка результатов запроса. Большинство БД, работающих с SQL, предоставляют специальные средства, позволяющие совершенствовать вывод запросов. Предположим, что есть необходимость выполнить простые числовые вычисления с данными, выводимыми в качестве результата запроса. SQL позволяет помещать выражения и константы среди выбранных полей. Эти выражения могут дополнять или замещать поля в предложениях SELECT, при этом они могут включать в себя одно или более выбранных полей. Например, если необходимо просмотреть проиндексированную стипендию, увеличив ее в два раза, то можно воспользоваться запросом: SELECT SFAM, SIMA, SOTCH, STIP*2 FROM STUDENTS; Часто возникает необходимость в размещении текста в выводе запроса. Например, для повышения удобства, работы с результатами предыдущего запроса, можно вставить сокращенное название единицы измерения проиндексированной стипендии - условных единиц, что выполняется следующим запросом: SELECT SFAM, SIMA, SOTCH, 'y.e.', STIP*2 FROM STUDENTS; Для упорядочения вывода полей таблиц SQL использует команду ORDER BY, позволяя сортировать вывод запроса согласно значениям в том или ином количестве выбранных столбцов. Если указывается несколько полей, то столбцы вывода упорядочиваются один внутри другого, при этом можно определять возрастание (ASC) или убывание (DESC) для каждого столбца. По умолчанию установлено возрастание. В качестве примера используем запрос, выводящий таблицу с информацией о студентах в алфавитном порядке фамилий: SELECT * FROM STUDENTS ORDER BY SFAM ASC; Пример для упорядочивания информации по нескольким столбцам. Например, информацию из таблицы с данными о студентах упорядочим по уменьшению размера стипендии, а для студентов, имеющих одинаковый ее размер - в алфавитном порядке их фамилий. Для этого воспользуемся запросом: SELECT * FROM STUDENTS ORDER BY STIP DESC, SFAM ASC; Аналогичным образом допускается использовать ORDER BY сразу с любым числом столбцов, однако поля, по которым происходит упорядочивание, должны быть указаны в SELECT. Поэтому запрос вида: SELECT SNUM, STIP FROM STUDENTS ORDER BY SFAM ASC; будет запрещен, т.к. поле SFAM не было выбранным полем, и GROUP BY не смог его найти для упорядочения вывода. ORDER BY может использоваться с GROUP BY для упорядочения групп, при этом ORDER BY должен быть последним. Например, выведем уже рассмотренный нами отчет о количестве студентов, получающих ту или иную стипендию, но с упорядочиванием по убыванию размеров их стипендий: SELECT COUNT (DISTINCT SNUM) , 'студ. получают стипендию ', STIP, ' у. е.' FROM STUDENTS GROUP BY STIP ORDER BY STIP DESC; Основная цель ключевого слова ORDER BY - дать возможность использовать эту команду со столбцами вывода так же, как и со столбцами таблицы - ведь иногда требуется произвести упорядочивание вывода по столбцам, производимым агрегатной функцией, константами или выражениями в предложении SELECT запроса. Например, попробуем рассмотреть отчет о количестве студентов, получающих ту или иную стипендию, но с упорядочиванием по убыванию количества студентов: SELECT COUNT (DISTINCT SNUM), 'студ. получают стипендию ', STIP, ' у. е.' FROM STUDENTS GROUP BY STIP ORDER BY 1 DESC; Следовательно, необходимо использовать номер столбца, т.к. столбец вывода не имеет имени; и нельзя использовать саму агрегатную функцию.

13.08.2019 1.56 Mб 2 Графика_Прогн_экономич_показ_1M.doc

31.07.2019 1.02 Mб 17 Графика_СПУ_Сокр.doc

01.05.2019 208.9 Кб 12 Грузоведение.doc

05.03.2016 37.26 Кб 33 Гусев.docx

05.03.2016 922.38 Кб 29 дипломная работа: "серые лесные почвы".rtf

19.08.2019 1.35 Mб 15 Для УМК БД.doc

05.03.2016 76.93 Кб 52 Документ Microsoft Office Word (2).docx

25.11.2019 49.36 Кб 29 Задание для РГР мясо.docx

05.03.2016 15.98 Mб 574 Задание по ИГ. Проекционное черчение.pdf

05.03.2016 25.59 Кб 42 Задание расчёты.docx

05.03.2016 261.63 Кб 99 Задание01.doc

Ограничение

Для продолжения скачивания необходимо пройти капчу:

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

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