- •Базы данных
- •Лекция 1 Хранение данных Данные, информация
- •Системы хранения данных на основе файлов
- •База данных
- •Требования к субд
- •Администратор бд (абд)
- •Лекция 2 Модели данных Независимость данных
- •Модель, схема
- •Сетевая модель
- •Лекция 3 Ранние модели Иерархическая модель
- •Лекция 4 Пример базы данных, построенной на сетевой модели Постановка задачи
- •Диаграмма
- •Описание на яод
- •Лекция 5 Реляционная модель Принципы
- •Уточнения
- •Лекция 6 Методы хранения данных и доступа к ним
- •Последовательный метод
- •Прямой метод
- •Индексные методы
- •Индексно-последовательный метод
- •Индексно-произвольный метод
- •Инвертированные списки
- •Хеширование
- •Лекция 7 Реляционная алгебра: определения, изменение отношений
- •Изменение отношений во времени.
- •Лекция 8 Операции реляционной алгебры
- •Булевы операции
- •Выбор; свойства выбора
- •Проекция; свойства проекции
- •Лекция 9 Операции реляционной алгебры (продолжение) Соединение
- •Свойства соединения
- •Лекция 10 Операции реляционной алгебры (продолжение)
- •Деление
- •Постоянные отношения. Переименование атрибутов
- •Эквисоединение, естественное и -соединение
- •Реляционная алгебра. Полнота ограниченного множества операторов
- •Операторы расщепления и фактора
- •Лекция 11 Язык структурных запросов sql
- •Начальные понятия
- •Стандарт ansi
- •Типы данных
- •Интерактивный и встроенный sql
- •Синтаксис
- •Подразделы sql
- •Простейшие действия
- •Функции агрегирования
- •Группировка
- •Возможности форматирования
- •Лекция 12 Язык структурных запросов sql (продолжение) Соединение
- •Вложенные запросы
- •Связанные запросы
- •Предикаты, определенные на подзапросах
- •Объединение
- •Изменение базы данных
- •Лекция 13 Понятие о нормальных формах
- •1 Нормальная форма (1нф)
- •2 Нормальная форма (2нф)
- •3 Нормальная форма (3нф)
- •Нормальная форма Бойса-Кодда (нфбк)
- •4 Нормальная форма (4нф)
- •5 Нормальная форма (5нф) – проекция/соединение
- •Лекция 13 Проектирование данных Процессы проектирования
- •Концептуальное проектирование
- •Логическое проектирование
- •Средства создания модели
- •Лекция 14 Функциональные зависимости
- •Аксиомы вывода
- •Ориентированный ациклический граф вывода
- •Определение реляционной базы данных
- •Представление множества функциональных зависимостей
- •Лекция 15 Покрытия функциональных зависимостей
- •Лемма об эквивалентности фз
- •Неизбыточные покрытия
- •Посторонние атрибуты
- •Канонические покрытия
- •Структура неизбыточных покрытий
- •Оптимальные покрытия
- •3 Нормальная форма
- •Нормализация через декомпозицию и посредством синтеза
- •Нормальная форма Бойса-Кодда
- •Литература
Вложенные запросы
В SQL множество значений может задаваться не только перечислением входящих в него элементов, но и запросом. Так же, как и список элементов, запрос заключается в круглые скобки. Полученное множество используется так же, как и рассмотренное ранее. Множество содержит атомарные элементы, поэтому формирующий его запрос должен выбирать только один атрибут. В результате запроса множество может быть пустым, содержать один элемент или более одного. Если множество содержит один элемент, оно может рассматриваться как обычное значение, и для него определены соответствующие операции сравнения. Для множества, содержащего более одного элемента, эти операции, естественно, недопустимы, определена лишь операция принадлежности элемента множеству. Заметим, что в результате запроса может образоваться несколько одинаковых значений и, как и в случае обычного запроса, по умолчанию все они включаются в выборку. То есть, на самом деле речь идет не о множестве, а о мультимножестве (комплекте). Использование варианта Distinct приводит к исключению повторяющихся элементов.
Так как запрос, формирующий множество, внешне выглядит как обычный, его называют вложенным запросом. Вложенный запрос сам может иметь вложенный запрос (FoxPro не поддерживает вложенность во вложенные запросы).
Пример
Найти все заказы, которые выполняет продавец Сидоров:
Select * From Заказы
Where ном_прод=(Select * From Продавцы Where имя_прод=’Сидоров’);
Запрос корректен, если есть ровно один продавец Сидоров. Если такого нет – результат не определен, если их более одного – результат ошибочен.
Найти все заказы, сумма которых больше, чем средняя за 4 октября:
Select * From Заказы
Where сумма>(Select AVG(сумма) From Заказы Where дата=’04.10’);
Найти все заказы для продавцов из Москвы:
Select * From Заказы
Where ном_прод in (Select ном_прод From Продавцы
Where город=’Москва’);
Такой же результат можно получить, используя операцию соединения:
Select a.* From Заказы a, Продавцы b
Where a.ном_прод = b.ном_прод and город=’Москва’;
Найти комиссионные всех продавцов, обслуживающих покупателей из Москвы:
Select комиссия From Продавцы
Where ном_прод in (Select ном_прод From Заказы
Where ном_пок in (Select ном_пок From Покупатели
Where город=’Москва’));
Определить количество покупателей, имеющих значимость, превышающую среднюю для покупателей из Тулы:
Select значимость, COUNT(Distinct ном_пок) From Покупатели
Having значимость > (Select AVG(значимость) From Покупатели
Where город=’Тула’);
Конец примера
Соединение и вложенные запросы, приведенные в примере, выполняются разными способами, поэтому, несмотря на то, что выборка получается одинаковой, время, затраченное на выполнение запроса, может существенно разниться. Это же касается и необходимой памяти. Выбор варианта неоднозначен, он зависит как от размеров таблиц, включая промежуточные, так и от используемой СУБД.
Связанные запросы
Для реализации вложенного запроса может потребоваться информация из таблиц внешнего запроса. Запросы такого типа называются связанными.
Пример
Выбрать всех покупателей, которые сделали заказы 3 октября:
Select * From Покупатели a
Where ’03.10’ in (Select дата From Заказы b Where a.ном_пок=b.ном_пок);
Конец примера
При вычислении простого вложенного запроса внутренний подзапрос вычисляется автономно до выполнения внешнего запроса. Связанный запрос так выполнен быть не может: выполнение внутреннего подзапроса зависит от состояния таблиц, объявленных во внешнем запросе. Следовательно, внутренний подзапрос должен выполняться для каждой строки внешней таблицы, от которой он зависит. Итак, сформулируем правила выполнения связанных запросов.
Выбрать очередную строку внешней таблицы, от которой зависит внутренний подзапрос, она называется строкой-кандидатом.
Сохранить ее под псевдонимом, указанном во внешней фразе From.
Выполнить подзапрос. Используемые в подзапросе значения строки-кандидата называются внешними ссылками.
Оценить результат внешнего запроса на основании результата подзапроса.
Повторить процедуру для следующих строк внешней таблицы.
Как и в случае вложенных запросов, связанный запрос можно заменить соединением. Здесь тоже нужно внимательно отнестись к выбору варианта, от этого может существенно зависеть производительность.
Пример
Реализовать предыдущий пример, используя соединение:
Select Distinct a.* From Покупатели a, Заказы b
Where a.ном_пок=b.ном_пок and дата=’03.10’;
Очевидно, Distinct в этом случае необходим, если хотя бы один покупатель сделал более одного заказа. В результате эта операция потребует значительного времени, что снизит эффективность запроса.
Выбрать имена и номера продавцов, обслуживающих более одного покупателя:
Select ном_прод, имя_прод From Продавцы a
Where 1<(Select COUNT(Distinct ном_пок) From Заказы
Where ном_прод=a.ном_прод);
Конец примера
Связанный запрос во внутреннем подзапросе может содержать ту же таблицу, что и во внешнем, то есть таблица связывается сама с собой. В этом случае одна и та же таблица в разных подзапросах играет разные роли, но обработка идет по приведенным ранее правилам. Разумеется, одновременно с выборкой строки-кандидата фиксируется и состояние таблицы, чтобы восстановить его после выполнения подзапроса.
Пример
Для каждого покупателя выбрать все заказы на сумму, большую средней суммы его заказов:
Select * From Заказы a
Where сумма>(Select AVG(сумма) From Заказы b
Where a.ном_пок=b.ном_пок);
Конец примера
Так же, как и в случае вложенного запроса, связанный подзапрос может использоваться во фразе Having, если условие накладывается на группу записей.
