Uploaded by m445ge

362061

advertisement
Лекция 4. Выборка данных
В лекции подробно рассматривается оператор выборки SELECT.
Приводятся примеры разных видов соединения таблиц при выборке данных.
Также затрагиваются вопросы аналитической выборки с использованием
группировки данных и агрегатных функций.
Цель: сформировать представление о возможностях и способах
использования оператора SELECT.
Целью любой системы управления базами данных является
осуществление операций над данными: ввод, изменение, удаление и выборка.
При этом выборка данных является наиболее часто используемым аспектом
управления данными. Выборка осуществляется с помощью одной единственной
команды SELECT, являющейся частью языка DML1 (Data Manipulation
Language – язык управления данными).
Результатом выполнения данной команды является итоговый набор
данных, состоящий из таких частей, как заголовки столбцов и записи данных.
Этот набор должен содержать не менее одного столбца, записи могут быть, а
могут и отсутствовать.
Команда SELECT состоит из семи основных частей: списка выборки и
разделов FROM, WHERE, GROUP BY, HAVING, ORDER BY и COMPUTE –
обязательным является лишь список выборки, при использовании же остальных
частей необходимо их использовать в том порядке, в котором они приведены
выше.
Простая выборка данных
Для простой выборки данных используется сокращенный синтаксис
оператора SELECT:
SELECT [ALL | DISTINCT] [TOP n [PERCENT] СписокВыборки
FROM ИмяТаблицы
WHERE УсловиеОтбора
СписокВыборки определяет поля, включаемые в итоговый набор данных,
ИмяТаблицы указывает таблицу БД, из которой возвращаются записи, а
УсловиеОтбора позволяется ограничить число возвращаемых записей с
помощью логических операторов.
По умолчанию команда SELECT возвращает все записи, включая
дубликаты, что определяется ключевым словом ALL, которое может быть
1
DML – это семейство компьютерных языков, используемых в компьютерных программах или
пользователями баз данных для получения, вставки, удаления или изменения данных в базах данных. SQL
является самым известным и используемым представителем языков данного семейства.
1
опущено. Для получения набора уникальных неповторяющихся записей
необходимо указывать ключевое слово DISTINCT.
Использование ключевого слова TOP предписывает выводить не все
записи итогового набора, а только n первых. Можно выбирать не
фиксированное количество записей, а определенный процент от всех строк –
для этого указывается ключевое слово PERCENT.
Список выборки
Список выборки может содержать включать следующие один или
несколько элементов:
* | ИмяПоля | Выражение [AS Псевдоним], [...n].
Для выборки всех полей из таблицы в списке выборки необходимо
указать звездочку (*).
Ключевое слово AS позволяет заменить в итоговом наборе данных
обычные имена полей псевдонимами. Имя псевдонима должно удовлетворять
стандартным правилам именования объектов. При необходимости включить
недопустимые символы, пробелы или национальные алфавиты, имя псевдонима
заключается в квадратные скобки.
Например, для получения списка стран с указанием их кода и последней
даты изменения записи из таблицы CountryRegion базы данных
AdventureWorks2008 необходимо выбрать поля CountryRegionCode, Name,
ModifiedDate:
SELECT
CountryRegionCode AS 'Код',
[Name] AS 'Страна',
ModifiedDate AS 'Дата изменения'
FROM Person.CountryRegion
При этом БД AdventureWorks должна быть текущей. Обратите внимание,
что перед названием таблицы используется еще название схемы Person,
предназначенной для управления объектами, связанными с работниками и
департаментами. Поля данных будут представлены пользователю в порядке,
определенном в списке выборки.
Элемент Выражение задает выражение, которое включается в итоговый
набор данных. Выражение может содержать константы, имена полей, функции
и их комбинации. По умолчанию имя колонки с выражением не определено,
поэтому можно указать псевдоним.
Например, список сотрудников с указанием фамилии и первого символа
имени и идентификационного номера может быть получен в результате
запроса:
SELECT LastName+’ ‘+Substring(FirstName,1,1)+’.’ AS [Сотрудник],
ContactID
FROM Person.Contact
2
Удобочитаемость получаемого набора данных может быть повышена
путем его сортировки в возрастающем или убывающем порядке. Сортировка
возможна по имени поля (даже если оно и не указано в списке выборки), по
псевдониму или по позиции в списке выборки, которые указываются в разделе
ORDER BY ИмяПоля [,…n] [ASC | DESC].
По умолчанию сортировка осуществляется по возрастанию, что
соответствует зарезервированному слову ASC, которое может опускаться, для
сортировки в убывающем порядке указывается – DESC.
Для отображения, рассмотренного ранее, списка сотрудников
упорядоченного в алфавитном порядке необходимо дополнить запрос:
SELECT LastName+’ ‘+Substring(FirstName,1,1)+’.’ AS [Сотрудник],
ContactID
FROM Person.Contact
ORDER BY [Сотрудник]
Условие отбора
Условие отбора определяет критерий отбора записей, включаемых в
итоговый набор. В результат будут включены только те строки, которые
соответствуют наложенным условиям.
Условие может включать выражения, образованные с помощью
операторов сравнения или логических операторов. Условия могут также
объединяться и с помощью логических операндов AND, OR и NOT.
Например, чтобы получить список товаров, цена которых находится в
диапазоне от $12 до $20, необходимо выполнить следующий запрос:
SELECT [Name], ListPrice
FROM Production.Product
WHERE (ListPrice>=12) and (ListPrice<=20)
ORDER by 2
Эти два оператора сравнения могут быть заменены одним логическим
оператором BETWEEN, с помощью которого можно получить ответ на вопрос,
лежит ли величина в указанном диапазоне.
SELECT [Name], ListPrice
FROM Production.Product
WHERE ListPrice BETWEEN 12 and 20
ORDER BY ListPrice
Данный оператор предназначен лишь для того, чтобы облегчить логику
восприятия алгоритма.
Для поиска по шаблону символьных строк используется логический
оператор LIKE, который чаще всего используется в ситуациях, когда
неизвестно точное совпадение.
В шаблоне могут использоваться следующие универсальные символы:
3
 % – подразумевает любую строку, состоящую из 0 и более символов;
 _ – ровно один символ;
 [ ] – любой символ из заданного множества (например, [adfh]) или
диапазона (например, [0-9]),
 [^] – любой символ, не попадающий в заданный диапазон или
множество.
Например, чтобы вывести имена сотрудников и их должностей,
проживающих за пределами США, необходимо выполнить запрос:
SELECT LastName, JobTitle
FROM HumanResources.vEmployee
WHERE CountryRegionName Not LIKE ‘%United States%’
Для определения соответствия выражения одному из перечисленных в
заданном списке значений применяется логический оператор IN. Данный
оператор всегда может быть записан и в виде группы условий, объединенных
операндом OR.
Например, с помощью следующего запроса может быть получен список
сотрудников из США и Канады:
SELECT LastName, JobTitle
FROM HumanResources.vEmployee
WHERE CountryRegionName IN (‘United States’, ‘Canada’)
Однако в список значений нельзя включать неопределенное значение
NULL, для работы с такими значениями используется функция выборки IS
NULL.
Например, следующий запрос возвращает список товаров, у которых не
указан цвет:
SELECT [Name]
FROM Production.Product
WHERE Color IS NULL
Выборка данных из нескольких таблиц
Такая выборка данных предполагает соединение нескольких таблиц для
получения единого набора результатов, включающих записи и поля каждой
таблицы. Соединение позволяет собрать данные, разделенные в процессе
нормализации.
Существует три вида соединений: внутреннее, внешнее и перекрестное.
Для объединения трех и более таблиц можно применять последовательность
соединений.
4
Для соединения таблиц необходимо раздел FROM дополнить ключевыми
словами JOIN, которое определяет соединяемые таблицы и метод соединения, и
ON, указывающее общие для таблиц поля.
Внутреннее соединение
При таком виде соединения сравниваются значения общих полей двух
таблиц, возвращаются только записи, удовлетворяющие критерию связывания в
обеих таблицах. Записи, для которых не имеется пары в связанной таблице, в
результат не включаются.
Например, в таблице Product нормализованной базы данных
AdventureWorks храниться только идентификатор категории товара. Чтобы
получить список товаров с указанием их категорий, необходимо соединить
таблицы Product и ProductSubcategory:
SELECT Product.Name, ProductSubcategory.Name, Product.ListPrice
FROM Production.Product INNER JOIN Production.ProductSubcategory
ON Product.ProductSubcategoryID =
ProductSubcategory.ProductSubcategoryID
При таком соединении товары, для которых не указана их категория, не
включаются в набор результатов.
Обратите внимание, что в разделе FROM необходимо указать имя схемы
Production, а в остальных случаях перед указанием поля используется имя
таблицы Product и ProductSubcategory для разрешения конфликтов, т.к. в обеих
таблицах присутствуют поля Name.
Внешнее соединение
Такое
соединение
также
возвращает
объединенные
записи,
соответствующие условию объединения. Однако левые и правые соединения
возвращают записи и не соответствующие указанному условию объединения.
Такие соединения применяются для получения полного набора записей одной
из таблиц.
При левом соединении в результат будут включены все записи левой
таблицы (имя которой расположено слева от JOIN), независимо от того, есть
для них соответствующая запись в правой таблице (имя таблицы расположено
справа от JOIN) или нет.
Например, следующий запрос возвращает имя контактного лица и дату
размещения заказа:
SELECT FirstName, LastName, OrderDate
FROM Person.Contact LEFT JOIN Sales.SalesOrderHeader
ON Contact.ContactID = SalesOrderHeader.ContactID
Для лиц, не размещавших заказы, в поле OrderDate содержится значение
NULL.
5
При правом соединении (ключевое слово RIGHT JOIN) в результат
включаются все записи правой таблицы, независимо от того, есть для них
соответствующая строка в левой таблице.
Измените рассмотренный запрос так, чтобы он выдавал такие же
результаты при использовании правого соединения.
Перекрестные соединения
При таком соединении выводятся все комбинации записей таблиц, при
этом не требуется указание совпадающих значений полей, поэтому условие ON
опускается.
В нормализованных базах данных перекрестные соединения чаще всего
используются для получения списка всех возможных комбинаций записей двух
таблиц, т.е. число записей итогового набора равняется произведения числа
записей первой таблицы на число записей второй.
Например, с помощью перекрестного соединения можно перечислить все
возможные способы поставки товаров в базе данных Northwind (поставлялась с
MS SQL Server до появления AdventureWorks):
SELECT DISTINCT Suppliers.Country, Orders.ShipCountry
FROM Suppliers CROSS JOIN Orders
Объединение нескольких наборов результатов
Оператор UNION объединяет результаты двух и более операторов
SELECT и применяется в случае, когда данные нельзя получить при помощи
одного запроса.
Для получения единого итогового набора данных необходимо написать
отдельные операторы SELECT и объединить их при помощи оператора UNION,
при этом, в отличие от соединения, записи в итоговый набор добавляются друг
за другом:
SELECT ...
UNION [ALL]
SELECT ...
[,...]
По умолчанию повторяющиеся записи удаляются, для получения всех
записей необходимо указать ключевое слово ALL. Необходимо также
учитывать, что список полей, порядок и все их свойства должны быть
одинаковы во всех используемых запросах.
Имена полей итогового набора берутся из первого запроса, поэтому
создание псевдонимов полей выполняется в нем. Для получения
отсортированного набора данных раздел ORDER BY указывается после
последнего оператора SELECT.
6
Аналитическая выборка данных
Аналитическая выборка данных из базы данных опирается на
возможности Transact-SQL создавать запросы, неразрывно связанных с
агрегатными функциями:
 Avg ([all | distinct] выражение) – среднее арифметическое всех
значений.
 Count ([all | distinct] выражение | *) – количество значений в списке,
отличных от NULL. При использовании символа * подсчитывается количество
значений, включая значения NULL или повторяющиеся значения.
 Sum ([all | distinct] выражение) – сумма всех значений списка.
 Max ([all | distinct] выражение) –максимальное значение.
 Min ([all | distinct] выражение) – минимальное значение.
Ключевое слово all предписывает выполнять агрегирование всех записей
в результирующем наборе данных, distinct – агрегирование только уникальных
записей. По умолчанию используется all.
Например, вычисление средней цены товаров осуществляется с помощью
следующего запроса:
SELECT AVG(ListPrice) FROM Production.Product
При выполнении агрегатной функции осуществляется объединение
значений отдельного поля таблицы или части записей, после чего выполняется
указанное агрегирование.
Агрегатная функция возвращает одно единственное значение, поэтому
использование других имен полей в списке выборки запрещено.
Подзапросы
Подзапрос – это оператор SELECT, включенный в другие запросы.
Подзапросы применяются для разбивки сложного запроса на серию логических
этапов. Их применение эффективно, если запрос использует записи,
возвращенные другим запросом.
Существует два вида подзапросов.
1) Вложенные подзапросы – возвращают единственное значение либо
список значений. Вложенный запрос выполняется один раз, а затем
результирующее значение используется во внешнем запросе.
Например, чтобы определить имена заказчиков, разместивших заказы в
последний учетный день, можно воспользоваться следующим запросом:
SELECT CustomerID
FROM Sales.SalesOrderHeader
WHERE OrderDate =
(SELECT Max(OrderDate) FROM Sales. SalesOrderHeader)
7
Выполнение этого запроса осуществляется в два этапа: на первом –
осуществляется выполнение подзапроса, как самостоятельного запроса,
который возвращает значение, используемое на втором этапе при выполнении
внешнего запроса.
В результате получаем имена и фамилии, которые могут быть
использованы в подзапросе для получения полного имени заказчика:
SELECT FirstName + ' ' + LastName AS 'CustomerName'
FROM Sales.vIndividualCustomer
WHERE CustomerID in
(SELECT CustomerID
FROM Sales.SalesOrderHeader
WHERE OrderDate=
(SELECT Max(OrderDate) FROM Sales. SalesOrderHeader))
Такой запрос может быть оформлен и в виде соединения таблиц. Такие
запросы обрабатываются значительно быстрее, поэтому если выполнение
запроса не требуется выполнять в несколько этапов, использование
подзапросов не обязательно.
2) Связанные подзапросы – используются данные внешнего запроса,
причем связанный запрос выполняется один раз для каждой записи внешнего
запроса.
Например, для определения списка заказчиков, заказавших за один раз
более 300 единиц товара, необходимо выполнить следующий запрос:
SELECT SalesOrderID, CustomerID
FROM Sales.SalesOrderHeader oh
WHERE 300 < (SELECT sum(OrderQty)
FROM Sales.SalesOrderDetail od
WHERE od.SalesOrderID = oh.SalesOrderID)
В связанных подзапросах, чтобы различать имена таблиц необходимо
применять их псевдонимы. В примере для таблицы SalesOrderHeader определен
псевдоним oh, а для SalesOrderDetail – od.
Однако использование связанных подзапросов неэффективно, лучше
преобразовывать их в соединения таблиц, что позволяет оптимизатору запросов
выбирать наилучший способ обработки данных.
Например, следующий запрос для каждого товара отображает сведения о
самом крупном его заказе: количество заказанного товара и номер заказа.
SELECT Name, OrderQty, SalesOrderID
FROM Production.Product p
INNER JOIN Sales.SalesOrderDetail od1 ON od1.ProductID=p.ProductID
WHERE OrderQty = (SELECT Max(OrderQty)
FROM Sales.SalesOrderDetail od2
WHERE od1.ProductID = od2.ProductID)
8
Группировка записей
Для группировки записей по полям или выражениям применяется раздел
GROUP BY оператора SELECT, что позволяет применять для каждой группы
функции агрегирования.
Синтаксис данной части следующий:
[GROUP BY ВыражениеГруппировки, [...n]]
Например, чтобы определить количество товаров в каждом заказе,
необходимо сгруппировать записи с одинаковым идентификационным номером
заказа SalesOrderID и подсчитать количество записей в каждой группе:
SELECT SalesOrderID, count(ProductID) AS [Количество]
FROM Sales.SalesOrderDetail
GROUP BY SalesOrderID
При использовании GROUP BY для каждой определенной группы
значений выводится только одна запись в итоговом наборе данных.
Если для каждого заказа еще необходимо подсчитать и общее количество
товаров в заказе, то запрос должен быть дополнен:
SELECT SalesOrderID,
count(ProductID) AS [Количество],
sum(OrderQty) AS [Сумма Товаров]
FROM Sales.SalesOrderDetail
GROUP BY SalesOrderID
При группировке записей допускается также использование раздела
WHERE, в этом случае группируются записи, удовлетворяющие этому условию.
Раздел WHERE позволяет определить, какие записи должны
подвергнуться группировке, а раздел HAVING – какие группы должны быть
выведены в итоговый набор данных. Ключевое слово HAVING можно
использовать только в разделе GROUP BY.
Так с помощью этого раздела можно в итоговый набор данных поместить
только те заказы, сумма товаров в которых превышает 150 единиц:
SELECT SalesOrderID,
count(ProductID) AS [Количество],
sum(OrderQty) AS [Сумма Товаров]
FROM Sales.SalesOrderDetail
GROUP BY SalesOrderID
HAVING sum(OrderQty) >= 150
Краткие итоги. Были рассмотрены основные варианты использования
оператора SELECT, возможность и необходимость соединения таблиц
9
(внутреннее, внешнее, перекрестное). Кроме того были изучены агрегатные
функции MS SQL Server и способы их применения в операторе SELECT.
10
Download