Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DB-Lab5.pdf
Скачиваний:
55
Добавлен:
21.03.2016
Размер:
444.5 Кб
Скачать

1

Лабораторная работа №5

ИЗУЧЕНИЕ ОПЕРАТОРА ВЫБОРКИ SELECT. ЗАПРОСЫ К СВЯЗАННЫМ ТАБЛИЦАМ.

ЗАПРОСЫ С ПОДЗАПРОСАМИ

Цель работы: Получить навыки создания запросов на выборку к нескольким связанным таблицам БД, а также запросов с подзапросами с помощью языка SQL.

Соединение таблиц

Для выборки данных из нескольких связанных таблиц используется операции соединения таблиц.

Различают следующие виды соединений:

1.Внутреннее соединение.

2.Внешнее левое соединение.

3.Внешнее правое соединение.

4.Декартово произведение.

Стандарт SQL-92 предусматривает два способа соединения таблиц:

1.Условие соединения указывается в предложении WHERE.

2.Условие соединения указывается в предложении FROM. Предпочтительней использовать 2-й способ. Далее будут

рассмотрены все перечисленные виды соединений.

Примеры запросов, приведенные ниже относятся к БД, рассмотренной в предыдущей работе.

Внутреннее соединение таблиц

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

Пример: Получить информацию о поставках в следующем виде:

2

а) соединение в предложении WHERE:

SELECT Поставщики.[Наименование поставщика], Поставки.[Номер детали], Поставки.Объём

FROM Поставщики, Поставки

WHERE Поставщики.[Номер поставщика]= Поставки.[Номер поставщика];

б) соединение в предложении FROM:

Синтаксис:

SELECT <список столбцов>

FROM <таблица 1> INNER JOIN <таблица 2>

ON <таблица 1>.<столбец 1> = <таблица 2>.<столбец 2>;

Выше рассмотренный пример можно записать следующим образом:

SELECT Поставщики.[Наименование поставщика], Поставки.[Номер детали], Поставки.Объём

FROM Поставщики INNER JOIN Поставки ON Поставщики.[Номер поставщика]=

Поставки.[Номер поставщика];

3

Соединить можно и более 2-х таблиц.

Пример: Получить информацию о поставках в следующем виде:

Наименование

Наименование

Объем

поставщика

детали

 

 

 

 

SELECT Поставщики.[Наименование поставщика], Детали.[Наименование детали], Поставки.Объём

FROM (Поставщики INNER JOIN Поставки ON Поставщики.[Номер поставщика]=

Поставки.[Номер поставщика]) INNER JOIN Детали ON Поставки.[Номер детали]=Детали.[Номер детали];

Внешнее левое и внешнее правое соединения

При внешнем левом соединении в результирующий набор данных обязательно включаются все записи из левой таблицы и такие записи из правой таблицы, для которых выполняется заданное условие связывания. Если запись из левой таблицы не имеет связанных записей в правой таблице, то недостающие поля в записи результирующего набора данных заполняются NULL значением. Внешнее левое соединение реализуется с помощью операции LEFT JOIN.

Аналогично, при внешнем правом соединении в результирующий набор данных обязательно включаются все записи из правой таблицы и такие записи из левой таблицы, для которых выполняется заданное условие связывания. Внешнее левое соединение реализуется с помощью операции RIGHT JOIN.

Пример: Получить информацию обо всех поставщиках, а также об объемах поставок, выполненных этими поставщиками, если поставки имели место.

4

С помощью внешнего левого соединения эта задача решается следующим образом:

SELECT Поставщики.[Наименование поставщика], Поставки.Объём

FROM Поставщики LEFT JOIN Поставки

ON Поставщики.[Номер поставщика] = Поставки.[Номер поставщика]

С помощью внешнего правого соединения эта задача решается

так:

SELECT Поставщики.[Наименование поставщика], Поставки.Объём

FROM Поставки RIGHT JOIN Поставщики ON Поставки.[Номер поставщика]= Поставщики.[Номер поставщика]

Результат будет один и тот же. В каждом конкретном случае следует использовать ту операцию, которая более удобна.

Декартово произведение

Декартово произведение позволяет получить в результирующем наборе данных все возможные сочетания записей из левой и правой таблиц. Если в левой таблице будет N записей, а в правой M записей, то в результирующем наборе данных будет NxM записей. Декартово произведение реализуется с помощью операции «,» в предложении

FROM.

Пример: Получить все возможные комбинации поставщиков и деталей.

SELECT Поставщики.[Наименование поставщика], Детали.[Наименование Детали]

FROM Поставщики, Детали

5

Декартово произведение часто используют в операторе INSERT INTO…SELECT для создания тестовых наборов данных для отладки БД.

Подзапросы

Подзапросом называют запрос на выборку, располагаемый в теле другого оператора языка SQL. Подзапросы могут использоваться в предложениях WHERE и HAVING оператора SELECT, а также в операторах DELETE и UPDATE. Некоторые СУБД позволяют использовать подзапросы в предложениях SELECT и FROM оператора

SELECT.

Подзапрос называется простым, если он может рассматриваться независимо от внешнего запроса. СУБД выполняют простой подзапрос один раз и затем помещают его результат во внешний запрос. Сложный подзапрос не может рассматриваться отдельно от внешнего запроса. В этом случае выполнение оператора начинается с выполнения внешнего запроса, который отбирает каждую отдельную строку таблицы, для каждой выбранной строки СУБД выполняет подзапрос один раз.

Существуют два типа подзапросов: скалярные и табличные. Скалярный подзапрос возвращает единственное значение.

Пример: Определить название деталей, цена которых больше цены детали "Болт".

6

SELECT [Наименование детали] FROM Детали

WHERE [Цена детали]>(SELECT [Цена детали] FROM Детали

WHERE [Наименование детали]='болт');

Пример: Определить номера деталей, цена которых меньше средней цены деталей.

SELECT [Номер детали]

FROM Детали

WHERE [Цена детали]<(SELECT AVG([Цена детали])

FROM Детали);

Пример: Определить номер детали, входящей в поставку с максимальным объемом.

SELECT [Номер детали]

FROM Поставки

WHERE Объём=(SELECT MAX(Объём)

FROM Поставки);

Табличные подзапросы могут возвращать множество значений, поэтому результат табличного подзапроса необходимо обрабатывать специальным образом.

Совместно с табличными подзапросами можно использовать операции EXISTS и NOT EXISTS, которые в зависимости от результатов выполнения принимают значения TRUE или FALSE. Если подзапрос возвращает хотя бы одну строку, то результатом выполнения EXISTS будет значение TRUE в противном случае (ни одна строка не возвращена) будет FALSE. Для проверки противоположного условия следует использовать операцию NOT EXISTS.

Пример: Определить наименования поставщиков, которые поставляют детали в настоящее время.

7

SELECT Поставщики.[Наименование поставщика] FROM Поставщики

WHERE EXISTS(SELECT *

FROM Поставки

WHERE Поставщики.[Номер поставщика]= Поставки.[Номер поставщика]);

Пример: Предыдущий запрос реализовать без использования подзапроса с помощью соединения таблиц:

SELECT DISTINCT Поставщики.[Наименование поставщика] FROM Поставщики INNER JOIN Поставки

ON Поставщики.[Номер поставщика]= Поставки.[Номер поставщика];

Два предыдущих запроса реализуют операцию пересечения.

Пример: Найти наименования деталей, цена которых меньше 20 и суммарная поставка более 500 штук.

SELECT [Наименование детали] FROM Детали

WHERE ([Цена детали]<20) AND EXISTS( SELECT Поставки.[Номер детали] FROM Поставки

WHERE Детали.[Номер детали]= Поставки.[Номер детали]

GROUP BY Поставки.[Номер детали] HAVING SUM(Объём)>500);

Операция вычитания EXPECT реализуется с помощью NOT EXISTS.

Пример: Определить наименования поставщиков, которые в настоящее время не поставляют деталей.

8

SELECT [Наименование поставщика] FROM Поставщики

WHERE NOT EXISTS(SELECT *

FROM Поставки

WHERE Поставщики.[Номер поставщика]= Поставки.[Номер поставщика]);

С подзапросами так же можно использовать операции IN и NOT

IN.

Пример: Определить наименования поставщиков, которые не поставляют детали

SELECT [Наименование поставщика]

FROM Поставщики

WHERE [Номер поставщика] NOT IN(

SELECT Поставки.[Номер поставщика]

FROM Поставки);

С подзапросами можно так же использовать операции ALL и ANY. Аналогом ANY является SOME. Если подзапросу предшествует ключевое слово ALL, условие сравнения считается выполненным, только если оно выполняется для всех значений подзапроса. Если Подзапросу предшествует ключевое слово ANY, условие сравнения считается выполненным, если оно выполняется хотя бы для одного из значений подзапроса.

Пример: Вывести наименования деталей с максимальной ценой.

SELECT [Наименование детали]

FROM Детали

WHERE [Цена детали]>=ALL(SELECT [Цена детали]

FROM Детали);

Пример: Определить наименования поставщиков, которые в данные момент поставляют детали.

SELECT [Наименование поставщика] FROM Поставщики

WHERE [Номер поставщика]=ANY(SELECT [Номер поставщика] FROM Поставки);

9

Сравнение эквивалентных запросов

Один и тот же запрос можно построить по-разному, однако от способа построения существенно зависит скорость выполнения запроса.

Пример: Определить наименования деталей, которые поставляются в настоящее время.

Решим задачу шестью способами. Все шесть способов реализуют операцию пересечения INTERSECT, которой нет в большинстве СУБД, а именно пересечения таблиц "Детали" и "Поставки".

1. С помощью операции ANY.

SELECT [Наименование детали]

FROM Детали

WHERE [Номер детали]=ANY(SELECT [Номер детали]

FROM Поставки);

2. С помощью операции EXISTS.

SELECT [Наименование детали] FROM Детали

WHERE EXISTS(SELECT *

FROM Поставки

WHERE Детали.[Номер детали]= Поставки.[Номер детали]);

3. С помощью операции IN.

SELECT [Наименование детали] FROM Детали

WHERE [Номер детали] IN(SELECT Поставки.[Номер детали] FROM Поставки);

4. С помощью операции INNER JOIN.

SELECT DISTINCT Детали.[Наименование детали] FROM Детали INNER JOIN Поставки

ON Детали.[Номер детали]= Поставки.[Номер детали];

10

5. С помощью операции WHERE.

SELECT DISTINCT Детали.[Наименование детали] FROM Детали, Поставки

WHERE Детали.[Номер детали]=Поставки.[Номер детали];

6. С помощью сложного подзапроса.

SELECT Детали.[Наименование детали] FROM Детали

WHERE 0<(SELECT COUNT(*) FROM Поставки

WHERE Детали.[Номер детали]= Поставки.[Номер детали]);

Самые эффективные запросы – 4 и 5, которые реализуются с помощью соединения таблиц. Средние по эффективности – 1 и 3, реализованные с помощью простых подзапросов. Наименее эффективными являются 2 и 6, так как реализованы с помощью сложных подзапросов.

Пример: Вывести информацию о деталях, которые не поставляются в настоящее время.

1. С помощью подзапроса.

SELECT [Номер детали], [Наименование детали] FROM Детали

WHERE 0=(SELECT COUNT(*) FROM Поставки

WHERE Детали.[Номер детали]= Поставки.[Номер детали]);

2. С помощью соединения таблиц.

SELECT Детали.[Номер детали], Детали.[Наименование детали], Детали.[Цена детали]

FROM Детали LEFT JOIN Поставки

11

ON Детали.[Номер детали]=Поставки.[Номер детали] WHERE Поставки.Объём IS NULL;

Пример: Определить номера поставщиков, которые одновременно поставляют деталь №1 "болт" и деталь №2 "гайка"

SELECT [Номер поставщика] FROM Поставки

WHERE [Номер детали]=1 AND [Номер поставщика] IN( SELECT Поставки.[Номер поставщика] FROM Поставки

WHERE [Номер детали]=2);

Самосоединение таблиц

Самосоединение – это обычное соединение в языке SQL, которое соединяет таблицу с самой собой. Также соединение позволяет сравнивать значение, которое хранится в одном столбце одной таблицы.

При самосоединении задаются так называемые алиасы или псевдонимы таблиц, которые вводятся в разделе FROM:

FROM <имя существующее таблицы> AS <алиас>

Алиасы используются как обычные имена таблиц в качестве префикса перед именем столбца.

Существуют два способа соединения:

1. С помощью предложения WHERE.

SELECT Поставки.[Номер поставщика] FROM Поставки, Поставки AS Поставки1 WHERE Поставки.[Номер детали]=1

AND PD1.[Номер детали]=3

AND Поставки.[Номер поставщика]= Поставки1.[Номер поставщика];

2. С помощью операции INNER JOIN.

12

SELECT Поставки.[Номер поставщика]

FROM Поставки INNER JOIN Поставки AS Поставки1 ON Поставки.[Номер поставщика]=

Поставки1.[Номер поставщика] WHERE Поставки.[Номер детали]=1

AND Поставки1.[Номер детали]=3;

13

Задание

Разработать запросы на языке SQL в соответствии с вариантом задания.

Вариант 1 Поставка товаров

1.Запросы на основе нескольких таблиц.

1.1.Изучение операции внутреннего соединения INNER JOIN.

1.1.1.Вывести информацию о поставках с указанием наименования поставщика.

1.1.2.Вывести следующую информацию о поставках: наименование поставщика, наименование товара, дата и объем поставки.

1.2.Изучение операций внешнего левого LEFT JOIN и правого

RIGHT JOIN соединений.

1.2.1.Вывести информацию обо всех потенциальных поставщиках, указав даты поставок, если такие поставки были.

1.2.2.Вывести информацию обо всех возможных товарах, указав объемы поставок, если такие поставки были.

1.3.Изучение операции декартова произведения для соединения таблиц (условие соединения указывается в предложении

WHERE).

1.3.1.Вывести следующую информацию о поставках: наименование поставщика, наименование товара, дата и объем поставки.

1.3.2.Вывести информацию обо всех возможных товарах, указав объемы поставок, если такие поставки были.

1.4.Использование псевдонимов для самосоединения таблиц.

1.4.1.Вывести номера поставщиков, которые поставляют как товар с номером 1, так и товар с номером 3.

1.5.Использование соединений таблиц при построении вычислений.

1.5.1.Вывести информацию о каждой поставке с указанием наименования поставщика, наименования товара, объема поставки, цены товара и стоимости поставки в рублях, долларах и евро.

1.5.2.Вывести информацию о количестве поставок каждого поставщика.

Для СУБД MS SQL Server

14

1.5.3.Вычислить среднюю стоимость поставок Рыбкина.

2.Запросы с подзапросами.

2.1.Изучение простых скалярных подзапросов.

2.1.1.Вывести информацию обо всех товарах, цена которых больше цены товара Ложка.

2.1.2.Вывести информацию о поставках, стоимость которых не ниже средней стоимости.

2.1.3.Вывести наименование поставщика для поставки с максимальной стоимостью.

2.2.Изучение простых табличных подзапросов с использованием операций IN, ALL, SOME, ANY.

2.2.1.Вывести список поставщиков, которые не поставляют никаких товаров.

2.2.2.Вывести наименования товаров, цена которых не меньше цены всех товаров.

2.2.3.Вывести наименования товаров, цена которых превышает цену хотя бы одного другого товара.

2.3.Изучение сложных подзапросов с использованием операции

EXISTS.

2.3.1.Вывести информацию о тех поставщиках, которые участвовали хотя бы в одной поставке.

2.3.2.Вывести информацию о товарах, ни разу никем не поставляемых.

2.4.Изучение подзапросов повышенной сложности.

2.4.1.Вывести список наименований поставщиков, которые поставляют ТОЛЬКО товар Вилка.

Вариант 2 Киносеанс

1.Запросы на основе нескольких таблиц.

1.1.Изучение операции внутреннего соединения INNER JOIN.

1.1.1.Вывести информацию о сеансах с указанием названия кинотеатра.

1.1.2.Вывести следующую информацию о сеансах: название кинотеатра, название кинофильма, дата, время и стоимость сеанса.

1.2.Изучение операций внешнего левого LEFT JOIN и правого

RIGHT JOIN соединений.

1.2.1.Вывести информацию обо всех кинофильмах, указав дату и время их показа, если такие показы были.

15

1.2.2.Вывести информацию обо всех существующих кинотеатрах, указав даты показа сеансов, если такие сеансы были.

1.3.Изучение операции декартова произведения для соединения таблиц (условие соединения указывается в предложении

WHERE).

1.3.1.Вывести следующую информацию о сеансах: название кинотеатра, название кинофильма, дата и время сеанса.

1.3.2.Вывести информацию обо всех существующих

кинотеатрах, указав даты показа сеансов, если такие сеансы были.

1.4.Использование псевдонимов для самосоединения таблиц.

1.4.1.Вывести номера кинотеатров, в которых показывают как кинофильм с кодом 1, так и кинофильм с кодом 3.

1.5.Использование соединений таблиц при построении вычислений.

1.5.1.Вывести информацию о каждом сеансе с указанием названия кинотеатра, названия кинофильма, даты и времени сеанса, а также стоимости сеанса в рублях, долларах и евро.

1.5.2.Вывести информацию о количестве сеансов в каждом кинотеатре.

1.5.3.Вычислить среднюю стоимость сеансов в кинотеатре

«Мир».

2.Запросы с подзапросами.

2.1.Изучение простых скалярных подзапросов.

2.1.1.Вывести информацию обо всех кинофильмах, год выпуска которых больше года выпуска кинофильма «Война и мир».

2.1.2.Вывести информацию о сеансах, стоимость которых не ниже средней стоимости сеанса.

2.1.3.Вывести название кинотеатра, в котором стоимость сеанса максимальна.

2.2.Изучение простых табличных подзапросов с использованием операций IN, ALL, SOME, ANY.

2.2.1.Вывести список кинотеатров, которые в настоящее время не показывают кинофильмов.

2.2.2.Вывести название кинофильмов, год выпуска которых не меньше года выпуска всех кинофильмов.

Для СУБД MS SQL Server

16

2.2.3.Вывести название кинофильмов, год выпуска которых превышает год выпуска хотя бы одного другого кинофильма.

2.3.Изучение сложных подзапросов с использованием операции

EXISTS.

2.3.1.Вывести информацию о тех кинофильмах, которые показывали хотя бы один раз.

2.3.2.Вывести информацию о кинофильмах, которые ни разу не показывали.

2.4.Изучение подзапросов повышенной сложности.

2.4.1.Вывести список названий кинофильмов, которые показывают ТОЛЬКО в кинотеатре «Мир».

Вариант 3 Поликлиника

1.Запросы на основе нескольких таблиц.

1.1.Изучение операции внутреннего соединения INNER JOIN.

1.1.1.Вывести информацию о талонах с указанием фамилии врача.

1.1.2.Вывести следующую информацию о талонах: фамилия

испециализация врача, фамилия пациента, номер кабинета, дата и время приема.

1.2.Изучение операций внешнего левого LEFT JOIN и правого

RIGHT JOIN соединений.

1.2.1.Вывести информацию обо всех врачах, указав дату и время приема, если к этим врачам были выписаны талоны.

1.2.2.Вывести информацию обо всех пациентах, указав даты приемов, если пациентам выдавались талоны.

1.3.Изучение операции декартова произведения для соединения таблиц (условие соединения указывается в предложении

WHERE).

1.3.1.Вывести следующую информацию о талонах: фамилия

испециализация врача, фамилия пациента, номер кабинета, дата и время приема.

1.3.2.Вывести информацию обо всех врачах, указав дату и

время приема, если к этим врачам были выписаны талоны.

1.4.Использование псевдонимов для самосоединения таблиц.

Для СУБД MS SQL Server

17

1.4.1.Вывести номера пациентов, которые посещают как врача с номером 1, так и врача с номером 3.

1.5.Использование соединений таблиц при построении вычислений.

1.5.1.Вывести информацию о каждом талоне с указанием фамилии врача, специализации, фамилии пациента, даты и времени приема, а также суммы страховой выплаты в рублях, долларах и евро.

1.5.2.Вывести информацию о количестве талонов к каждому врачу.

1.5.3.Вычислить среднюю сумму страховых выплат по талонам для врача Иванова.

2.Запросы с подзапросами.

2.1.Изучение простых скалярных подзапросов.

2.1.1.Вывести информацию обо всех пациентах, возраст которых больше возраста пациента Иванова.

2.1.2.Вывести информацию о талонах, сумма страховой выплаты которых не ниже средней суммы страховой выплаты по всем талонам.

2.1.3.Вывести фамилию врача, к которому был выписан талон с минимальной суммой страховой выплаты.

2.2.Изучение простых табличных подзапросов с использованием операций IN, ALL, SOME, ANY.

2.2.1.Вывести список врачей, к которым не было выписано ни одного талона.

2.2.2.Вывести фамилии пациентов, год рождения которых не меньше года рождения всех пациентов.

2.2.3.Вывести фамилии пациентов, год рождения которых превышает год рождения хотя бы одного другого пациента.

2.3.Изучение сложных подзапросов с использованием операции

EXISTS.

2.3.1.Вывести информацию о тех пациентах, которые хотя бы один раз были у врача.

2.3.2.Вывести информацию о пациентах, которые ни разу не были у стоматолога.

2.4.Изучение подзапросов повышенной сложности.

2.4.1.Вывести список фамилий пациентов, которые посещают ТОЛЬКО врача-стоматолога.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]