Инструкция SQL SELECT возвращает результирующий набор записей из одной или нескольких таблиц . [1] [2]
Инструкция SELECT извлекает ноль или несколько строк из одной или нескольких таблиц или представлений базы данных . В большинстве приложений SELECT
это наиболее часто используемая команда языка манипулирования данными (DML). Поскольку SQL является декларативным языком программирования , SELECT
запросы указывают набор результатов, но не указывают, как его вычислять. База данных преобразует запрос в « план запроса », который может различаться в зависимости от исполнения, версии базы данных и программного обеспечения базы данных. Эта функция называется « оптимизатором запросов », поскольку она отвечает за поиск наилучшего плана выполнения запроса в рамках применимых ограничений.
Инструкция SELECT имеет множество необязательных предложений:
SELECT
Предложение — это список столбцов или выражений 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 допускает именованные подзапросы, называемые общими табличными выражениями (названные и разработанные в честь реализации IBM DB2 версии 2; Oracle называет их факторингом подзапросов ). CTE также могут быть рекурсивными , ссылаясь на себя; Полученный механизм позволяет осуществлять обход деревьев или графов (когда они представлены в виде отношений) и, в более общем плане, вычисления с фиксированной точкой .
Производная таблица — это использование ссылки на подзапрос SQL в предложении 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 уникален, каждая строка всегда будет иметь уникальный номер строки.
Оконная RANK() OVER
функция действует как ROW_NUMBER, но может возвращать больше или меньше n строк в случае равенства, например, чтобы вернуть 10 самых молодых людей:
SELECT * FROM ( SELECT RANK () OVER ( ORDER BY age ASC ) AS рейтинг , person_id , person_name , возраст FROM person ) AS foo WHERE рейтинг <= 10
Приведенный выше код может возвращать более десяти строк, например, если есть два человека одного возраста, он может возвращать одиннадцать строк.
Поскольку пределы результатов ISO SQL:2008 можно указать, как показано в следующем примере, с помощью этого FETCH FIRST
предложения.
ВЫБРАТЬ * ИЗ T ВЫБРАТЬ ТОЛЬКО ПЕРВЫЕ 10 СТРОК
В настоящее время это предложение поддерживается CA DATACOM/DB 11, IBM DB2, SAP SQL Anywhere, PostgreSQL, EffiProz, H2, HSQLDB версии 2.0, Oracle 12c и Mimer SQL .
Microsoft SQL Server 2008 и более поздних версий поддерживает FETCH FIRST, но это считается частью этого ORDER BY
предложения. Для этого использования необходимы все предложения , ORDER BY
и OFFSET
.FETCH FIRST
ВЫБРАТЬ * ИЗ T ЗАКАЗАТЬ ПО столбцу DESC OFFSET 0 СТРОК ВЫБРАТЬ ТОЛЬКО ПЕРВЫЕ 10 СТРОК
Некоторые СУБД предлагают нестандартный синтаксис вместо стандартного синтаксиса SQL или в дополнение к нему. Ниже приведены варианты простого запроса лимита для разных СУБД:
Разбиение на страницы [9] — это подход, используемый для ограничения и отображения только части общих данных запроса в базе данных. Вместо одновременного отображения сотен или тысяч строк серверу запрашивается только одна страница (ограниченный набор строк, например только 10 строк), и пользователь начинает навигацию, запрашивая следующую страницу, а затем следующую. , и так далее. Это очень полезно, особенно в веб-системах, где нет выделенного соединения между клиентом и сервером, поэтому клиенту не нужно ждать, чтобы прочитать и отобразить все строки сервера.
{rows}
= Количество строк на странице{page_number}
= Номер текущей страницы{begin_base_0}
= Номер строки – 1, где начинается страница = (номер_страницы-1) * строки{begin_base_0 + 1}
и{begin_base_0 + rows}
Выберите * из { таблицы } в порядке { unique_key }
{begin_base_0 + rows}
){begin_base_0 + rows}
строки, но отправьте их на отображение только тогда, когда row_number считанных строк больше, чем{begin_base_0}
{rows}
строки, начиная со следующей строки ( {begin_base_0 + 1}
){rows}
строки с фильтром:{rows}
строки, в зависимости от типа базы данных.{rows}
строки, в зависимости от типа базы данных, где {unique_key}
больше {last_val}
(значение {unique_key}
последней строки на текущей странице){rows}
строки, где {unique_key}
меньше {first_val}
(значение {unique_key}
первой строки на текущей странице), и отсортируйте результат в правильном порядке.Некоторые базы данных предоставляют специальный синтаксис для иерархических данных .
Оконная функция в SQL:2003 — это агрегатная функция, применяемая к разделу набора результатов.
Например,
сумма ( население ) БОЛЬШЕ ( РАЗДЕЛЕНИЕ ПО городам )
вычисляет сумму населения всех строк, имеющих то же значение города , что и текущая строка.
Разделы указываются с помощью предложения OVER , которое изменяет агрегат. Синтаксис:
< OVER_CLAUSE > :: = OVER ( [ РАЗДЕЛЕНИЕ ПО < выражение > , ... ] [ ORDER BY < выражение > ])
Предложение OVER позволяет разделить и упорядочить набор результатов. Порядок используется для функций, связанных с порядком, таких как row_number.
Обработка оператора SELECT в соответствии с ANSI SQL будет следующей: [10]
выберите г. _ * от пользователей и внутренних групп объединения g на g . Идентификатор пользователя = ты . Идентификатор пользователя , где вы . LastName = 'Смит' и ты . Имя = 'Джон'
выбрать тебя . * из пользователей, которых вы покинули, присоединяйтесь к группам g на g . Идентификатор пользователя = ты . Идентификатор пользователя , где вы . LastName = 'Смит' и ты . Имя = 'Джон'
выберите г. _ GroupName , считайте ( g . * ) как NumberOfMembers от пользователей из внутренних групп объединения g на g . Идентификатор пользователя = ты . Группа идентификаторов пользователей по имени группы
выберите г. _ GroupName , считайте ( g . * ) как NumberOfMembers от пользователей из внутренних групп объединения g на g . Идентификатор пользователя = ты . Группа идентификаторов пользователей по имени группы , имеющая количество ( g . * ) > 5
Реализация оконных функций поставщиками реляционных баз данных и механизмов SQL сильно различается. Большинство баз данных поддерживают по крайней мере некоторые разновидности оконных функций. Однако если мы присмотримся повнимательнее, станет ясно, что большинство поставщиков реализуют лишь часть стандарта. Давайте возьмем в качестве примера мощное предложение RANGE. Только Oracle, DB2, Spark/Hive и Google Big Query полностью реализуют эту функцию. Совсем недавно поставщики добавили к стандарту новые расширения, например, функции агрегирования массивов. Они особенно полезны в контексте запуска SQL в распределенной файловой системе (Hadoop, Spark, Google BigQuery), где у нас более слабые гарантии совместной локальности данных, чем в распределенной реляционной базе данных (MPP). Вместо того, чтобы равномерно распределять данные по всем узлам, механизмы SQL, выполняющие запросы к распределенной файловой системе, могут обеспечить гарантии совместной локальности данных за счет вложения данных и, таким образом, избегания потенциально дорогостоящих объединений, связанных с тяжелым перетасовкой по сети. Определяемые пользователем агрегатные функции, которые можно использовать в оконных функциях, являются еще одной чрезвычайно мощной функцией.
Метод генерации данных на основе объединения всех
выбрать 1 a , 1 b объединить все выбрать 1 , 2 объединить все выбрать 1 , 3 объединить все выбрать 2 , 1 объединить все выбрать 5 , 1
SQL Server 2008 поддерживает «конструктор строк», указанный в стандарте SQL3 («SQL:1999»).
выберите * из ( значения ( 1 , 1 ), ( 1 , 2 ), ( 1 , 3 ), ( 2 , 1 ), ( 5 , 1 )) как x ( a , b )
Хотя аргумент UNIQUE идентичен аргументу DISTINCT, он не является стандартом ANSI.
[...] ключевое слово DISTINCT [...] удаляет дубликаты из набора результатов.