Инструкция SQL SELECT возвращает результирующий набор строк из одной или нескольких таблиц . [1] [2]
Инструкция SELECT извлекает ноль или несколько строк из одной или нескольких таблиц или представлений базы данных . В большинстве приложений SELECT
это наиболее часто используемая команда языка манипулирования данными (DML). Поскольку SQL является декларативным языком программирования , SELECT
запросы указывают набор результатов, но не указывают, как его вычислять. База данных преобразует запрос в « план запроса », который может различаться в зависимости от исполнения, версии базы данных и программного обеспечения базы данных. Эта функция называется « оптимизатором запросов », поскольку она отвечает за поиск наилучшего плана выполнения запроса в рамках применимых ограничений.
Инструкция SELECT имеет множество необязательных предложений:
SELECT
list — это список столбцов или выражений SQL, возвращаемых запросом. Это примерно операция проецирования реляционной алгебры .AS
опционально предоставляет псевдоним для каждого столбца или выражения в SELECT
списке. Это операция переименования реляционной алгебры .FROM
указывает, из какой таблицы следует получить данные. [3]WHERE
указывает, какие строки следует получить. Это примерно операция выбора реляционной алгебры .GROUP BY
группирует строки, имеющие общее свойство, чтобы к каждой группе можно было применить агрегатную функцию .HAVING
выбирает одну из групп, определенных предложением GROUP BY.ORDER BY
указывает, как упорядочить возвращаемые строки.SELECT
— это наиболее распространенная операция в SQL, называемая «запрос». SELECT
извлекает данные из одной или нескольких таблиц или выражений. Стандартные SELECT
операторы не оказывают постоянного воздействия на базу данных. Некоторые нестандартные реализации SELECT
могут иметь постоянные последствия, например синтаксис, SELECT INTO
предусмотренный в некоторых базах данных. [4]
Запросы позволяют пользователю описывать желаемые данные, предоставляя системе управления базами данных (СУБД) выполнение планирования , оптимизации и выполнения физических операций, необходимых для получения результата по ее выбору.
Запрос включает список столбцов, которые должны быть включены в окончательный результат, обычно сразу после SELECT
ключевого слова. Звездочку (" *
") можно использовать, чтобы указать, что запрос должен возвращать все столбцы всех запрошенных таблиц. SELECT
— это самый сложный оператор SQL с необязательными ключевыми словами и предложениями, в том числе:
FROM
, указывающее таблицы, из которых нужно получить данные. Это FROM
предложение может включать необязательные JOIN
подпункты, определяющие правила объединения таблиц.WHERE
предложение включает предикат сравнения, который ограничивает строки, возвращаемые запросом. Это WHERE
предложение исключает из набора результатов все строки, в которых предикат сравнения не имеет значения True.GROUP BY
предложении строки, имеющие общие значения, проецируются на меньший набор строк. GROUP BY
часто используется в сочетании с функциями агрегации SQL или для исключения повторяющихся строк из набора результатов. Это WHERE
предложение применяется перед GROUP BY
предложением.HAVING
включает в себя предикат, используемый для фильтрации строк, полученных из этого GROUP BY
предложения. Поскольку он действует на результаты предложения GROUP BY
, в предикате предложения можно использовать функции агрегирования HAVING
.ORDER BY
предложение определяет, какие столбцы следует использовать для сортировки результирующих данных и в каком направлении их сортировать (по возрастанию или по убыванию). Без ORDER BY
предложения порядок строк, возвращаемых запросом SQL, не определен.DISTINCT
слово [5] исключает дублирование данных. [6]Следующий пример запроса SELECT
возвращает список дорогих книг. Запрос извлекает все строки из таблицы Book , в которых столбец цены содержит значение больше 100,00. Результат сортируется в порядке возрастания названия . Звездочка (*) в списке выбора указывает, что все столбцы таблицы Book должны быть включены в набор результатов.
ВЫБЕРИТЕ * ИЗ Забронировать ГДЕ цена > 100 . 00 ПОРЯДОК ПО названию ;
В приведенном ниже примере демонстрируется запрос нескольких таблиц, группировка и агрегирование, возвращая список книг и количество авторов, связанных с каждой книгой.
ВЫБРАТЬ книгу . title AS Название , количество ( * ) AS Авторы ИЗ Книги ПРИСОЕДИНЯЙТЕСЬ Book_author ON Book . isbn = Автор_книги . isbn ГРУППИРОВАТЬ ПО Книге . заголовок ;
Пример вывода может выглядеть следующим образом:
Название Авторы---------------------- -------Примеры SQL и руководство 4Радость SQL 1Введение в SQL 2Подводные камни SQL 1
При условии, что isbn является единственным общим именем столбца в двух таблицах и что столбец с именем title существует только в таблице Book , можно переписать приведенный выше запрос в следующей форме:
ВЫБРАТЬ название , количество ( * ) КАК Авторы ИЗ Книги ЕСТЕСТВЕННОЕ ПРИСОЕДИНЕНИЕ Автор_книги ГРУППИРОВАТЬ ПО названию ;
Однако многие поставщики [ quantify ] либо не поддерживают этот подход, либо требуют определенных соглашений об именах столбцов для эффективной работы естественных объединений.
SQL включает операторы и функции для вычисления значений хранимых значений. SQL позволяет использовать выражения в списке выбора для проецирования данных, как в следующем примере, который возвращает список книг стоимостью более 100,00 с дополнительным столбцом sales_tax , содержащим сумму налога с продаж, рассчитанную в размере 6% от цены .
ВЫБЕРИТЕ isbn , название , цену , цену * 0 . 06 AS sales_tax ОТ Книга ГДЕ цена > 100 . 00 ПОРЯДОК ПО названию ;
Запросы могут быть вложенными, чтобы результаты одного запроса можно было использовать в другом запросе с помощью оператора отношения или функции агрегирования. Вложенный запрос также известен как подзапрос . В то время как соединения и другие табличные операции во многих случаях обеспечивают превосходные в вычислительном отношении (т.е. более быстрые) альтернативы (все зависит от реализации), использование подзапросов вводит иерархию в выполнении, которая может быть полезной или необходимой. В следующем примере функция агрегирования AVG
получает на вход результат подзапроса:
ВЫБЕРИТЕ isbn , название , цену ИЗ книги ГДЕ цена < ( ВЫБЕРИТЕ AVG ( цена ) ИЗ книги ) ПОРЯДОК ПО названию ;
Подзапрос может использовать значения из внешнего запроса, и в этом случае он называется коррелированным подзапросом .
С 1999 года стандарт SQL допускает предложения With, т.е. именованные подзапросы, часто называемые общими табличными выражениями (названные и разработанные в честь реализации IBM DB2 версии 2; Oracle называет их факторингом подзапросов ). CTE также могут быть рекурсивными , ссылаясь на себя; результирующий механизм позволяет осуществлять обход деревьев или графов (когда они представлены в виде отношений) и, в более общем плане, вычисления с фиксированной точкой .
Производная таблица — это подзапрос в предложении FROM. По сути, производная таблица представляет собой подзапрос, который можно выбрать или к которому можно присоединиться. Функциональность производной таблицы позволяет пользователю ссылаться на подзапрос как на таблицу. Производная таблица также называется встроенным представлением или выбором из списка .
В следующем примере оператор SQL включает соединение исходной таблицы «Книги» с производной таблицей «Продажи». Эта производная таблица собирает связанную информацию о продажах книг с использованием ISBN для присоединения к таблице «Книги». В результате производная таблица предоставляет результирующий набор с дополнительными столбцами (количество проданных товаров и компания, продавшая книги):
ВЫБРАТЬ б . исбн , б . титул , б . цена , продажа . items_sold , продажи . Company_nm FROM Book_Sales GROUP BY Company_Nm , ISBN ) продажи ON продажи . исбн = б . исбн
Учитывая таблицу T, запрос приведет к отображению всех элементов всех строк таблицы.SELECT * FROM T
Для той же таблицы запрос приведет к отображению элементов из столбца C1 всех строк таблицы. Это похоже на проекцию в реляционной алгебре , за исключением того, что в общем случае результат может содержать повторяющиеся строки. В некоторых терминах базы данных это также называется вертикальным разделением, ограничивающим вывод запроса для просмотра только определенных полей или столбцов.SELECT C1 FROM T
В той же таблице запрос приведет к отображению всех элементов всех строк, где значение столбца C1 равно «1» — в терминах реляционной алгебры выбор будет выполнен из-за предложения WHERE. Это также известно как горизонтальное разделение, ограничивающее вывод строк по запросу в соответствии с указанными условиями.SELECT * FROM T WHERE C1 = 1
При наличии более чем одной таблицы результирующим набором будет каждая комбинация строк. Таким образом, если две таблицы — это T1 и T2, в результате будет каждая комбинация строк T1 с каждой строкой T2. Например, если T1 имеет 3 строки, а T2 — 5 строк, то в результате получится 15 строк.SELECT * FROM T1, T2
Хотя это и не стандартно, большинство СУБД позволяют использовать предложение выбора без таблицы, делая вид, что используется воображаемая таблица с одной строкой. В основном это используется для выполнения расчетов, где таблица не нужна.
Предложение SELECT определяет список свойств (столбцов) по имени или подстановочный знак («*»), обозначающий «все свойства».
Часто бывает удобно указать максимальное количество возвращаемых строк. Это можно использовать для тестирования или для предотвращения чрезмерного потребления ресурсов, если запрос возвращает больше информации, чем ожидалось. Подход к этому часто варьируется в зависимости от поставщика.
В ISO SQL:2003 наборы результатов могут быть ограничены с помощью
В ISO SQL:2008 введен этот FETCH FIRST
пункт.
Согласно документации PostgreSQL v.9, оконная функция SQL «выполняет вычисления для набора строк таблицы, которые каким-то образом связаны с текущей строкой», аналогично агрегатным функциям. [7] Название напоминает оконные функции обработки сигналов . Вызов оконной функции всегда содержит предложение OVER .
ROW_NUMBER() OVER
может использоваться для простой таблицы с возвращаемыми строками, например, для возврата не более десяти строк:
SELECT * FROM ( SELECT ROW_NUMBER () OVER ( ORDER BY sort_key ASC ) AS номер_строки , столбцы ИЗ имени таблицы ) AS foo WHERE номер_строки <= 10
ROW_NUMBER может быть недетерминированным : если sort_key не уникален, каждый раз при выполнении запроса можно получить разные номера строк, назначенные любым строкам, где sort_key один и тот же. Если sort_key уникален, каждая строка всегда будет иметь уникальный номер строки.
The RANK() OVER
window function acts like ROW_NUMBER, but may return more or less than n rows in case of tie conditions, e.g. to return the top-10 youngest persons:
SELECT * FROM ( SELECT RANK() OVER (ORDER BY age ASC) AS ranking, person_id, person_name, age FROM person) AS fooWHERE ranking <= 10
The above code could return more than ten rows, e.g. if there are two people of the same age, it could return eleven rows.
Since ISO SQL:2008 results limits can be specified as in the following example using the FETCH FIRST
clause.
SELECT * FROM T FETCH FIRST 10 ROWS ONLY
This clause currently is supported by CA DATACOM/DB 11, IBM DB2, SAP SQL Anywhere, PostgreSQL, EffiProz, H2, HSQLDB version 2.0, Oracle 12c and Mimer SQL.
Microsoft SQL Server 2008 and higher supports FETCH FIRST, but it is considered part of the ORDER BY
clause. The ORDER BY
, OFFSET
, and FETCH FIRST
clauses are all required for this usage.
SELECT * FROM T ORDER BY acolumn DESC OFFSET 0 ROWS FETCH FIRST 10 ROWS ONLY
Some DBMSs offer non-standard syntax either instead of or in addition to SQL standard syntax. Below, variants of the simple limit query for different DBMSes are listed:
Rows Pagination[9] is an approach used to limit and display only a part of the total data of a query in the database. Instead of showing hundreds or thousands of rows at the same time, the server is requested only one page (a limited set of rows, per example only 10 rows), and the user starts navigating by requesting the next page, and then the next one, and so on. It is very useful, specially in web systems, where there is no dedicated connection between the client and the server, so the client does not have to wait to read and display all the rows of the server.
{rows}
= Number of rows in a page{page_number}
= Number of the current page{begin_base_0}
= Number of the row - 1 where the page starts = (page_number-1) * rows{begin_base_0 + 1}
and {begin_base_0 + rows}
Select * from {table} order by {unique_key}
{begin_base_0 + rows}
){begin_base_0 + rows}
rows but send to display only when the row_number of the rows read is greater than {begin_base_0}
{rows}
rows starting from the next row to display ({begin_base_0 + 1}
){rows}
rows with filter:{rows}
rows, depending on the type of database{rows}
rows, depending on the type of database, where the {unique_key}
is greater than {last_val}
(the value of the {unique_key}
of the last row in the current page){rows}
rows, where the {unique_key}
is less than {first_val}
(the value of the {unique_key}
of the first row in the current page), and sort the result in the correct orderSome databases provide specialised syntax for hierarchical data.
A window function in SQL:2003 is an aggregate function applied to a partition of the result set.
For example,
sum(population) OVER( PARTITION BY city )
calculates the sum of the populations of all rows having the same city value as the current row.
Partitions are specified using the OVER clause which modifies the aggregate. Syntax:
<OVER_CLAUSE> :: = OVER ( [ PARTITION BY <expr>, ... ] [ ORDER BY <expression> ] )
The OVER clause can partition and order the result set. Ordering is used for order-relative functions such as row_number.
The processing of a SELECT statement according to ANSI SQL would be the following:[10]
select g.*from users u inner join groups g on g.Userid = u.Useridwhere u.LastName = 'Smith'and u.FirstName = 'John'
select u.*from users u left join groups g on g.Userid = u.Useridwhere u.LastName = 'Smith'and u.FirstName = 'John'
select g.GroupName, count(g.*) as NumberOfMembersfrom users u inner join groups g on g.Userid = u.Useridgroup by GroupName
select g.GroupName, count(g.*) as NumberOfMembersfrom users u inner join groups g on g.Userid = u.Useridgroup by GroupNamehaving count(g.*) > 5
The implementation of window function features by vendors of relational databases and SQL engines differs wildly. Most databases support at least some flavour of window functions. However, when we take a closer look it becomes clear that most vendors only implement a subset of the standard. Let's take the powerful RANGE clause as an example. Only Oracle, DB2, Spark/Hive, and Google Big Query fully implement this feature. More recently, vendors have added new extensions to the standard, e.g. array aggregation functions. These are particularly useful in the context of running SQL against a distributed file system (Hadoop, Spark, Google BigQuery) where we have weaker data co-locality guarantees than on a distributed relational database (MPP). Rather than evenly distributing the data across all nodes, SQL engines running queries against a distributed filesystem can achieve data co-locality guarantees by nesting data and thus avoiding potentially expensive joins involving heavy shuffling across the network. User-defined aggregate functions that can be used in window functions are another extremely powerful feature.
Method to generate data based on the union all
select 1 a, 1 b union allselect 1, 2 union allselect 1, 3 union allselect 2, 1 union allselect 5, 1
SQL Server 2008 supports the "row constructor" feature, specified in the SQL:1999 standard
select *from (values (1, 1), (1, 2), (1, 3), (2, 1), (5, 1)) as x(a, b)
Although the UNIQUE argument is identical to DISTINCT, it is not an ANSI standard.
[...] the keyword DISTINCT [...] eliminates the duplicates from the result set.