- •Вопросы для подготовки к экзамену
- •1) Бд и файловые системы
- •2) Субд определение, функции
- •3) Субд определение, классификация
- •4) Бд основные определения, классификация
- •5) Объекты базы данных
- •Пользователи – лица, обладающие доступом к бд Роли позволяют объединять пользователей в группы
- •6) Физическая структура базы данных
- •7) Структурная часть реляционной модели
- •8) Фундаментальные свойства отношений
- •9) Реляционная алгебра Кодда
- •1. Оператор соединения
- •11) Этапы разработки бд
- •12) Нормальные формы отношений
- •13) Модель сущность-связь
- •14) Технология "клиент-сервер"
- •15) Обзор ms sql Server, клиентские приложения, системные таблицы
- •3. Утилиты командной строки
- •16) Основы языка sql, типы команд
- •17) Основной синтаксис оператора select
- •18) Построение нетривиальных запросов с использованием оператора select
- •19) Операторы dml
- •20) Операторы ddl
- •21) Операторы ddl (определение структуры таблицы)
- •22) Индексы в среде ms sql Server
- •23) Представления
- •24) Сценарии
- •25) Хранимые процедуры
- •26) Понятие функции
- •27) Триггеры
- •28) Курсоры
18) Построение нетривиальных запросов с использованием оператора select
Параметр Join
При работе в нормализованном окружении часто возникает ситуация, когда не вся необходимая информация находится в одной таблице. Именно в таких ситуациях необходимо применять параметр JOIN.
Параметр JOIN помещает (объединяет) информацию из двух таблиц в одно результирующее множество, которое можно представить в виде “виртуальной таблицы”. С этим множеством можно работать как с обычной таблицей и использовать его для других подзапросов.
Способ объединения таблиц задается выбором одного из четырех различных видов JOIN. Общим для всех видов JOIN является то, что они для одной записи некоторой таблицы находят одну или более соответствующих записей в других таблицах чтобы создать запись-супермножество, которая будет содержать поля обеих записей.
Базовый синтаксис JOIN выглядит следующим образом.
SELECT <SELECT-список>
FROM <первая_таблица>
<тип_объединения> <вторая_таблица>
[ON <условие_объединения>]
Параметр INNER JOIN является наиболее распространенным видом JOIN, он объединяет записи на основе одного или более общих полей, но возвращает только те записи, для которых имеет место соответствие по полям, указанным в JOIN.
SELECT <SELECT-список>
FROM <первая_таблица>
INNER JOIN <вторая_таблица>
ON <условие_объединения>
Если использовать * в списке полей вывода, тогда будут возвращены все столбцы таблиц.
Для того чтобы * использовать для отдельной таблицы, нужно указать следующим образом:
SELECT Orders.*, CompanyName
FROM Orders
INNER JOIN Customers ON Orders.CustomerID=Customers.CustomerID
Если необходимо обратиться к столбцу, имя которого присутствует более одного раза в JOIN-результате, нужно полностью определить имя столбца:
Таблица.ИмяСтолбца, Псевдоним.ИмяСтолбца
OUTER JOIN
SELECT <SELECT-список>
FROM <первая_таблица (считается левой)>
{LEFT|RIGHT|FULL} [OUTER] JOIN <вторая_таблица (считается правой)>
ON <условие_объединения>
OUTER JOIN является включающим объединением. Объединение происходит по совпадающим данным, но также в случае LEFT включается вся информация из левой таблицы, RIGHT- из правой, FULL включает всю информацию из обеих таблиц.
CROSS JOIN (перекрестное объединение) объединяет каждую запись с одной стороны JOIN с каждой записью с другой стороны JOIN.
SELECT <SELECT-список>
FROM <первая_таблица >
CROSS JOIN <вторая_таблица >
UNION – специальный оператор, с помощью которого можно построить из двух или более запросов одно результирующее множество.
По сути работа этого параметра похожа на присоединение выходных данных одного запроса к выходным данным другого запроса:
- Все запросы, объединенные этим оператором должны иметь одинаковое количество столбцов в SELECT-списке.
- В качестве заголовков столбцов результирующего множества будут использоваться заголовки столбцов первого запроса.
- Тип данных каждого столбца должен быть хотя бы неявно совместим с типом данных соответствующего столбца другого запроса.
- По умолчанию используется режим вывода DISTINCT, а не ALL.
Использование в объединении производных таблиц
Производная таблица создается из столбцов и строк, полученных в результате запроса.
Для её создания необходимо заключить запрос в скобки и задать для результата запроса псевдоним.
Затем эту производную таблицу можно использовать в операторе JOIN как обычную.
Вывести названия компаний, заказавших ‘Chocolade’ и ‘Tofu’
SELECT DISTINCT c.CompanyName FROM dbo.Customers c
INNER JOIN
(SELECT CustomerID FROM dbo.Orders o
INNER JOIN dbo.[Order Details] od ON o.OrderID=od.OrderID
INNER JOIN dbo.Products p ON p.ProductID=od.ProductID
WHERE p.ProductName='Chocolade') AS choc
ON c.CustomerID=choc.CustomerID
INNER JOIN
(SELECT CustomerID FROM dbo.Orders o
INNER JOIN dbo.[Order Details] od ON o.OrderID=od.OrderID
INNER JOIN dbo.Products p ON p.ProductID=od.ProductID
WHERE p.ProductName='Tofu') AS T
ON c.CustomerID=T.CustomerID
Понятие подзапроса
Часто невозможно решить поставленную задачу путем одного запроса. Это особенно актуально, когда при использовании условия поиска в предложении WHERE значение, с которым надо сравнивать, заранее не определено и должно быть вычислено в момент выполнения оператора SELECT.
В таком случае приходят на помощь законченные операторы SELECT, внедренные в тело другого оператора SELECT.
Внутренний подзапрос представляет собой также оператор SELECT, а кодирование его предложений подчиняется тем же правилам, что и основного оператора SELECT.
Внешний оператор SELECT использует результат выполнения внутреннего оператора для определения содержания окончательного результата всей операции. Внутренние запросы могут быть помещены непосредственно после оператора сравнения (=, <, >, <=, >=, <>) в списке полей вывода оператора SELECT, в предложения WHERE и HAVING внешнего оператора SELECT – они получают название подзапросов или вложенных запросов.
Подзапрос – это инструмент создания временной таблицы, содержимое которой извлекается и обрабатывается внешним оператором.
Текст подзапроса должен быть заключен в скобки.
К подзапросам применяются следующие правила и ограничения:
- фраза ORDER BY не используется, хотя и может присутствовать во внешнем подзапросе;
- список в предложении SELECT состоит из имен отдельных столбцов или составленных из них выражений – за исключением случая, когда в подзапросе присутствует ключевое слово EXISTS;
- по умолчанию имена столбцов в подзапросе относятся к таблице, имя которой указано в предложении FROM. Однако допускается ссылка и на столбцы таблицы, указанной во фразе FROM внешнего запроса, для чего применяются квалифицированные имена столбцов (т.е. с указанием таблицы);
- если подзапрос является одним из двух операндов, участвующих в операции сравнения, то запрос должен указываться в правой части этой операции.
Можно выделить типы подзапросов:
1. Скалярный подзапрос возвращает единственное значение. В принципе, он может использоваться везде, где требуется указать единственное значение.
2. Табличный подзапрос возвращает множество значений, т.е. значения одного или нескольких столбцов таблицы, размещенные в более чем одной строке. Он возможен везде, где допускается наличие таблицы.
Определить Номер компании, сделавшей самый последний заказ
SELECT CustomerID FROM Orders
WHERE OrderDate=(SELECT MAX(OrderDate) FROM Orders)
Указать для каждого заказа номер, стоимость, и отклонение стоимости данного заказа от максимальной стоимости заказа
SELECT OrderID, SUM(UnitPrice*Quantity*(1-Discount)) as Summ,
SUM(UnitPrice*Quantity*(1-Discount))-
(SELECT TOP 1 SUM(UnitPrice*Quantity*(1-Discount)) FROM [Order Details]
GROUP BY OrderID
ORDER BY SUM(UnitPrice*Quantity*(1-Discount))DESC)
FROM [Order Details]
GROUP BY OrderID
Подзапросы, возвращающие множество значений
Во многих случаях значение, подлежащее сравнению в предложениях WHERE или HAVING, представляет собой не одно, а несколько значений.
Вложенные подзапросы генерируют непоименованное промежуточное отношение, временную таблицу. Оно может использоваться только в том месте, где появляется в подзапросе. К такому отношению невозможно обратиться по имени из какого-либо другого места запроса. Применяемые к подзапросу операции основаны на тех операциях, которые, в свою очередь, применяются к множеству, а именно:
- { WHERE | HAVING } выражение [ NOT ] IN (подзапрос);
- { WHERE | HAVING } выражение оператор_сравнения { ALL | SOME | ANY }(подзапрос);
- {WHERE | HAVING } [ NOT ] EXISTS (подзапрос);
Использование операций IN и NOT IN
Оператор IN используется для сравнения некоторого значения со списком значений, при этом проверяется, входит ли значение в предоставленный список или сравниваемое значение не является элементом представленного списка.
Определить номера заказов, сделанных клиентами из Berlin
SELECT OrderID FROM Orders
WHERE CustomerID IN
(SELECT CustomerID FROM Customers WHERE City=‘Berlin’)
Использование ключевых слов ANY и ALL
Ключевые слова ANY и ALL могут использоваться с подзапросами, возвращающими один столбец чисел.
Если подзапросу будет предшествовать ключевое слово ALL, условие сравнения считается выполненным, только когда оно выполняется для всех значений в результирующем столбце подзапроса.
Если записи подзапроса предшествует ключевое слово ANY, то условие сравнения считается выполненным, когда оно выполняется хотя бы для одного из значений в результирующем столбце подзапроса.
Если в результате выполнения подзапроса получено пустое значение, то для ключевого слова ALL условие сравнения будет считаться выполненным, а для ключевого слова ANY – невыполненным. Ключевое слово SOME является синонимом слова ANY.
Все эти операторы применяется с любыми операторами сравнения
Найти номера заказов, сделанных в 1996 году, в которых количество товара с номером 36, превышает хотя бы раз такой же показатель в заказах 1998 на этот товар.
SELECT [Order Details].OrderID,Quantity FROM [Order Details] INNER JOIN Orders
ON [Order Details].OrderID=Orders.OrderID
WHERE Quantity>SOME
(SELECT Quantity FROM [Order Details] INNER JOIN Orders
ON [Order Details].OrderID=Orders.OrderID
WHERE ProductID=36 AND YEAR(OrderDate)=1998)
AND ProductID=36 AND YEAR(OrderDate)=1996
Использование операций EXISTS и NOT EXISTS
Ключевые слова EXISTS и NOT EXISTS предназначены для использования только совместно с подзапросами.
Результат их обработки представляет собой логическое значение TRUE или FALSE.
Для ключевого слова EXISTS результат равен TRUE в том и только в том случае, если в возвращаемой подзапросом результирующей таблице присутствует хотя бы одна строка.
Если результирующая таблица подзапроса пуста, результатом обработки операции EXISTS будет значение FALSE.
Для ключевого слова NOT EXISTS используются правила обработки, обратные по отношению к ключевому слову EXISTS.
Поскольку по ключевым словам EXISTS и NOT EXISTS проверяется лишь наличие строк в результирующей таблице подзапроса, то эта таблица может содержать произвольное количество столбцов.
Определить названия компаний, разместивших по крайней мере один заказ
SELECT CompanyName FROM Customers cu
WHERE EXISTS
(SELECT OrderID FROM Orders o WHERE o.CustomerID=cu.CustomerID )
Коррелированные подзапросы
Коррелированные подзапросы от обычных вложенных отличает то, что обмен информацией между коррелированными подзапросами и основными запросами осуществляется в обоих направлениях. Вложенные запросы обычно обрабатываются только один раз, затем информация возвращается во внешний запрос, который затем тоже выполняется один раз.
В коррелированных подзапросах внутренний запрос выполняется на основе информации, переданной из внешнего запроса, и наоборот.
Коррелированные запросы в параметре WHERE:
Определить Номер заказа и дату заказа для первого заказа каждого из клиентов
SELECT o1.CustomerID, o1.OrderID,o1.OrderDate
FROM Orders o1
WHERE o1.OrderDate=(SELECT MIN(o2.OrderDate) FROM Orders o2 WHERE o2.CustomerID=o1.CustomerID)
ORDER BY CustomerID
Коррелированные запросы в списке полей оператора SELECT:
Получить название компании и дату заказа, сделанного этой компанией в первый раз
SELECT cu.CompanyName,
(SELECT MIN(OrderDate) FROM Orders o WHERE o.CustomerID=cu.CustomerID)
FROM Customers cu