Знакомство с инструкцией SELECT

Завершено

Transact-SQL или T-SQL — разновидность языка SQL стандарта ANSI, используемого продуктами и службами Microsoft SQL. Он аналогичен стандартному SQL. Большая часть внимания здесь будет уделяться инструкции SELECT, которая обладает большей частью возможностей и вариаций любой инструкции DML.

Начнем с подробного обзора того, как обрабатывается инструкция SELECT. Порядок содержимого в инструкции SELECT не является порядком, в котором она обрабатывается ядром СУБД SQL Server.

Обратите внимание на следующий запрос:

SELECT OrderDate, COUNT(OrderID) AS Orders
FROM Sales.SalesOrder
WHERE Status = 'Shipped'
GROUP BY OrderDate
HAVING COUNT(OrderID) > 1
ORDER BY OrderDate DESC;

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

Предложение SELECT возвращает столбец OrderDate и количество значений OrderID, которому присваивается имя (или псевдоним) Orders:

SELECT OrderDate, COUNT(OrderID) AS Orders

Предложение FROM определяет, какая таблица является источником строк для запроса; в данном случае это таблица Sales.SalesOrder:

FROM Sales.SalesOrder

Предложение WHERE фильтрует строки из результатов, сохраняя только те строки, которые соответствуют указанному условию; в данном случае это заказы с состоянием "shipped":

WHERE Status = 'Shipped'

Предложение GROUP BY принимает строки, удовлетворяющие условиям фильтра, и группирует их по параметру OrderDate; в результате все строки с одинаковым значением OrderDate рассматриваются как одна групп, и для каждой группы возвращается одна строка:

GROUP BY OrderDate

После формирования групп предложение HAVING фильтрует группы на основе собственного предиката. В результаты будут включаться только даты с более чем одним заказом:

HAVING COUNT(OrderID) > 1

Для предварительного просмотра этого запроса, последним предложением которого будет ORDER BY, которое сортирует выходные данные в порядке убывания согласно OrderDate:

ORDER BY OrderDate DESC;

Теперь, когда вы видели, что делает каждое предложение, давайте посмотрим на порядок, в котором SQL Server действительно оценивает их:

  1. Сначала вычисляется предложение FROM, чтобы предоставить исходные строки для остальной части инструкции. Создается виртуальная таблица, и затем передается на следующий шаг.
  2. Далее необходимо вычислить предложение WHERE, чтобы отфильтровать строки из исходной таблицы, соответствующие предикату. Отфильтрованная виртуальная таблица передается на следующий шаг.
  3. Здесь предложение GROUP BY упорядочивает строки в виртуальной таблице в соответствии с уникальными значениями, найденными в списке GROUP BY. Создается новая виртуальная таблица, содержащая список групп, и она передается на следующий шаг. С этого момента в потоке операций другие элементы могут ссылаться только на столбцы в списке GROUP BY или функциях агрегации.
  4. Далее вычисляется предложение HAVING путем фильтрации целых групп на основе его предиката. Виртуальная таблица, созданная на шаге 3, фильтруется и передается на следующий шаг.
  5. В конце выполняется предложение SELECT, определяя, какие столбцы будут отображаться в результатах запроса. Поскольку предложение SELECT вычисляется после выполнения других шагов, любые псевдонимы столбцов (в нашем примере Orders) не могут использоваться в предложении GROUP BY или HAVING.
  6. Предложение ORDER BY является последним выполняемым и оно сортирует строки согласно списку столбцов.

Чтобы применить это понимание к нашему примеру запроса, ниже приведен логический порядок выполнения инструкции SELECT, рассмотренной выше:

FROM Sales.SalesOrder
WHERE Status = 'Shipped'
GROUP BY OrderDate 
HAVING COUNT(OrderID) > 1
SELECT OrderDate, COUNT(OrderID) AS Orders
ORDER BY OrderDate DESC;

Не все возможные предложения необходимы во всех используемых инструкциях SELECT. Единственным обязательным предложением является предложение SELECT, которое в некоторых случаях можно использовать самостоятельно. Обычно для указания запрашиваемой таблицы также добавляется предложение FROM. Кроме того, в языке Transact-SQL есть другие предложения, которые можно добавить.

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

Выбор всех столбцов

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

Простейшая форма предложения SELECT: использовать символ звездочки (*), чтобы вернуть все столбцы. При использовании в запросах T-SQL он называется звездочка. Хотя SELECT * подходит для быстрой проверки, не следует использовать его в рабочей среде по нижеуказанным причинам.

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

Например, в следующем примере извлекаются все столбцы из (гипотетической) таблицы Production.Product.

SELECT * FROM Production.Product;

Результатом этого запроса является набор строк, содержащий все столбцы для всех строк таблицы, которые могут выглядеть примерно так:

ProductID

Имя.

ProductNum

Color

StandardCost

ПрейскурантнаяЦена

Размер

Вес

ProductCatID

680

HL Road Frame - Black, 58

FR-R92B-58

Черный

1059.31

1431.5

58

1016.04

18

706

HL Road Frame - Red, 58

FR-R92R-58

Красный

1059.31

1431.5

58

1016.04

18

707

Шлем Sport-100, красный

HL-U509-R

Красный

13.0863

34.99

35

708

Шлем Sport-100, черный

HL-U509

Черный

13.0863

34.99

35

...

...

...

...

...

...

...

...

...

Выбор конкретных столбцов

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

Например, рассмотрим следующий запрос; при этом используется гипотетическая таблица Production.Product.

SELECT ProductID, Name, ListPrice, StandardCost
‎FROM Production.Product;

На этот раз результаты содержат только указанные столбцы:

ProductID

Имя.

ПрейскурантнаяЦена

StandardCost

680

HL Road Frame - Black, 58

1431.5

1059.31

706

HL Road Frame - Red, 58

1431.5

1059.31

707

Шлем Sport-100, красный

34.99

13.0863

708

Шлем Sport-100, черный

34.99

13.0863

...

...

...

...

Выбор выражений

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

Например, следующий запрос содержит два выражения:

SELECT ProductID,
      Name + '(' + ProductNumber + ')',
  ListPrice - StandardCost
FROM Production.Product;

Результаты этого запроса могут выглядеть примерно так:

ProductID

680

HL Road Frame - Black, 58(FR-R92B-58)

372.19

706

HL Road Frame - Red, 58(FR-R92R-58)

372.19

707

Sport-100 Helmet, Red(HL-U509-R)

21.9037

708

Sport-100 Helmet, Black(HL-U509)

21.9037

...

...

...

Здесь следовало бы отметить несколько интересных особенностей.

  • Столбцы, возвращаемые двумя выражениями, не имеют имен столбцов. В зависимости от инструмента, используемого для отправки запроса, имя отсутствующего столбца может быть указано пустым заголовком столбца, литералом "Без имени столбца" или именем по умолчанию, например column1. Далее в этом разделе мы покажем, как указать псевдоним для имени столбца в запросе.
  • Первое выражение использует оператор + для (посимвольного) сцепления значений, а второе выражение использует оператор - для вычитания одного числового значения из другого. При использовании с числовыми значениями оператор + выполняет сложение. Очевидно, что важно понимать типы данных столбцов, добавляемых в выражения. Типы данных мы рассмотрим в следующем разделе.

Указание псевдонимов столбцов

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

Например, вот тот же запрос, что и раньше, но с псевдонимами, указанными для каждого столбца:

SELECT ProductID AS ID,
      Name + '(' + ProductNumber + ')' AS ProductName,
  ListPrice - StandardCost AS Markup
FROM Production.Product;

Результаты этого запроса содержат указанные имена столбцов:

ID

НаименованиеПродукта

Разметка

680

HL Road Frame - Black, 58(FR-R92B-58)

372.19

706

HL Road Frame - Red, 58(FR-R92R-58)

372.19

707

Sport-100 Helmet, Red(HL-U509-R)

21.9037

708

Sport-100 Helmet, Black(HL-U509)

21.9037

...

...

...

Примечание.

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

Форматирование запросов

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

Придерживайтесь следующих рекомендаций, чтобы сделать код T-SQL легко читаемым (и, следовательно, легко понимаемым и легко отлаживаемым!):

  • Записывайте прописью ключевые слова T-SQL, например SELECT, FROM, AS и т. д. Ключевые слова прописью — это часто используемое соглашение, которое упрощает поиск предложений в сложной инструкции.
  • Начинайте каждое основное предложение инструкции с новой строки.
  • Если список SELECT содержит больше нескольких столбцов, выражений или псевдонимов, рекомендуем перечислять каждый столбец в отдельной строке.
  • Используйте отступы для строк, содержащих вложенные предложения или столбцы, чтобы показать, какой код относится к какому основному предложению.