10.3. Реляционное исчисление
Как отмечалось ранее, принципиальное различие между реляционной алгеброй и реляционным исчислением состоит в том, что в первом случае процесс получения искомого результата описывается явным образом путем указания набора операций, которые надо выполнить для получения результата, а во втором — указываются свойства искомого отношения без конкретизации процедуры его получения.
Внешне подходы сильно различаются: один из них предписывающий (реляционная алгебра), а другой описательный (реляционное исчисление). На более низком уровне рассмотрения подходы эквивалентны, так как любые выражения реляционной алгебры могут быть преобразованы в семантически эквивалентные выражения реляционного исчисления и наоборот. Возможность такого преобразования доказывалась многими авторами, в частности, для этого можно использовать алгоритм редукции Кодда.
Для названного алгоритма преобразования покажем на содержательном уровне возможности формулировки одного и того же запроса с помощью реляционной алгебры и реляционного исчисления на простом примере.
• S (поставщики);
• Р (детали);
• SP (поставки).
Первичными ключами этих таблиц являются соответственно: П# (код поставщика), Д# (код детали) и составной ключ (П#, Д#). Содержимое таблиц приведено на рис. 3.7. Для удобства изложения предположим, что в рассматриваемых языках запросов нет ограничений на употребление символов русского алфавита в именах атрибутов. Каждое из полей П# и Д# таблицы SP в отдельности является внешним ключом по отношению к таблице S и Р соответственно.
Предположим, что имена доменов (множеств допустимых значений) совпадают с именами атрибутов. Исключение составляют атрибуты Город_П (город, в котором находится поставщик) и Город_Д (город, в котором выпускается деталь), которые имеют общий домен: множество названий городов. Имя этого домена может быть, например, просто Город. Характеристики доменов как типов данных следующие: Д# — строка символов длиной 5, Имя — строка символов длиной 20, Статус — цифровое длиной 5, Город — строка символов длиной 15, Д# — строка символов длиной 6, Тип — строка символов длиной 6, Вес — цифровое длиной 5, Количество — цифровое длиной 5.
S
П#
|
Имя
|
Статус
|
Город_П
|
S1
|
Сергей
|
20
|
Москва
|
S2
|
Иван
|
10
|
Киев
|
S3
|
Борис
|
30
|
Киев
|
S4
|
Николай
|
20
|
Москва
|
S5
|
Андрей
|
30
|
Минск
|
Р
Д#
|
Название
|
Тип
|
Вес
|
Город_Д .
|
Р1
|
гайка
|
каленый
|
12
|
Москва
|
Р2
|
болт
|
мягкий
|
17
|
Киев
|
РЗ
|
винт
|
твердый
|
17
|
Ростов
|
Р4
|
винт
|
каленый
|
14
|
Москва
|
Р5
|
палец
|
твердый
|
12
|
Киев
|
Р6
|
шпилька
|
каленый
|
19
|
Москва
|
SP
П#
|
Д#
|
Количество
|
S1
|
P1
|
300
|
S1
|
P2
|
200
|
S1
|
P3
|
400
|
S1
|
P4
|
200
|
S1
|
P5
|
100
|
S1
|
P6
|
100
|
S2
|
P1
|
300
|
S2
|
P2
|
400
|
S3
|
P2
|
200
|
S4 /
|
P2
|
200
|
S4
|
P4
|
300
|
S4
|
P5
|
400
|
Рис. 3.7. Таблицы поставщиков, деталей и поставок
Пусть запрос выглядит следующим образом: "Получить номера и города поставщиков, выпускающих деталь Р2".
Словесно алгебраическая версия этого запроса описывается так:
• образовать естественное соединение отношений S и SP по атрибуту П#;
• выбрать из результата этого соединения кортежи с деталью Р2 (в поле Д# должна быть строка Р2);
• спроецировать результат предыдущей операции на атрибуты П# и Город_П. Этот же запрос в терминах реляционного исчисления можно сформулировать примерно так: "Получить атрибуты П# и Город_П для таких поставщиков, для которых существует поставка в отношении SP с тем же значением атрибута П# и со значением Р" атрибута Д#".
Результатом выполнения запроса будет отношение R вида:
П#
|
ГородП
|
S1
|
Москва
|
S2
|
Киев
|
S3
|
Киев
|
S4
|
Москва
|
Читатель может самостоятельно убедиться в этом, проделав описанные выше операции реляционной алгебры.
Преимуществом реляционного исчисления перед реляционной алгеброй можно считать то, что пользователю не требуется самому строить алгоритм выполнения запроса. Программа СУБД (при достаточной ее интеллектуальности) сама строит эффективный алгоритм.
Отметим, что поставленную задачу выборки можно решить более оптимально с точки зрения потребности в оперативной памяти. Более экономичный вариант решения в терминах операциях реляционной алгебры выглядит так:
• выбрать из отношения SP кортежи, относящиеся к детали Р2;
• выполнить естественное соединение отношения S и отношения, полученного на предыдущем шаге;
• спроецировать текущее отношение на атрибуты П# и Город_П.
Экономия памяти при реализации этого алгоритма в сравнении с первоначальным вариантом достигается за счет снижения размерности участвующих в операциях временных таблиц, необходимых для хранения промежуточных результатов. Если в предыдущем случае размерность временной таблицы была 12*6 (12 строк на 6 колонок), то в последнем случае — 4*6.
Математической основой реляционного исчисления является исчисление предикатов — один из разделов математической логики. Понятие реляционного исчисления как языка работы с базами данных впервые предложено Коддом. Им же был разработан язык ALPHA — прототип программно реализованного языка QUEL, который некоторое время конкурировал с языком SQL.
Существует два варианта исчислений: исчисление кортежей и исчисление доменов. В первом случае для описания отношений используются переменные, допустимыми значениями которых являются кортежи отношения, а во втором случае — элементы домена.
Реляционное исчисление, основанное на кортежах (исчисление кортежей), предложено и реализовано при разработке упоминавшегося языка ALPHA. В нем, как и в процедурных языках программирования, сначала нужно описать используемые переменные, а затем записывать некоторые выражения.
Описательную часть исчисления можно представить в виде:
RANGE OF <переменная> IS <список>,
где прописными буквами записаны ключевые слова языка, <переменная> — идентификатор переменной кортежа (области значений), а <список> — последовательность одного или более элементов, разделенных запятыми, т. е. конструкция вида:
x1[,x2[, ..., xi] ...].
Вся конструкция RANGE указывает идентификатор переменной и область ее допустимых значений. Список элементов x1[,x2[, ..., xi] ...] содержит элементы, каждый. из которых является либо отношением, либо выражением над отношением (порядок записи выражений описывается далее). Все элементы списка должны быть совместимы по типу, т. е. соответствующие элементам отношения должны иметь идентичные заголовки. Область допустимых значений <переменной> образуется путем объединения значений всех элементов списка. Так, запись вида RANGE OF Т IS X1, Х2 означает, что область определения переменной Т включает в себя все значения, из отношения, которое является объединением отношений X1 и Х2.
Пример 1. Варианты описаний.
RANGE OF SX IS S;
RANGE OF SPX IS SP;
RANGE OF SY IS (SX) WHERE SX.Гopoд_П = 'Москва', (SX) WHERE EXISTS SPX (SPX.П# = SX.П# AND SPX.Д# = 'P1');
Переменные SX и SPX в первых двух примерах определены соответственно на отношениях S и SP соответственно (рис. 3.7). Третий пример иллюстрирует запись выражений при определении переменной кортежа. Переменная SY здесь может принимать значения из множества кортежей отношения S для поставщиков из Москвы или поставщиков, которые поставляют деталь Р1 (или для тех и других).
Синтаксис выражений исчисления рассматривается ниже. Запись выражения, формулирующего запрос на языке исчисления кортежей с помощью формы Бэкуса-Наура, упрощенно можно представить следующим образом:
<выражение> ::= (у, [, у; [..., у^ ]...]) [ WHERE wff]
у ::= {<переменная> | <переменная>.<атрибут> } [ AS <атрибут> ]
wff::=-<ycлoвиe> |
NOT wff |
< ycлoвиe >AND wff|
<условие> OR wff|
IF< условие >THEN wff |
EXISTS <переменная> (wff) |
FORALL <переменная> (wff) |
(wff)
Общий смысл записи выражения состоит в перечислении атрибутов результирующего (целевого) отношения, атрибуты которого должны удовлетворять условию истинности формулы wff (well formulated formula — правильно построенная формула). Список атрибутов целевого отношения, или целевой список, в терминах реляционной алгебры по существу определяет операцию проекции, а формула wff — селекцию кортежей.
В паре <переменная>.<атри6ут> первая составляющая служит для указания переменной кортежа (определенной конструкцией RANGE), а вторая — для определения атрибута отношения, на котором изменяется переменная кортежа. Необязательная часть "AS <атрибут>" используется для переименования целевого отношения. Если она отсутствует, то имя атрибута целевого отношения наследуется от соответствующего имени атрибута исходного отношения.
Употребление в качестве элемента целевого отношения просто имени переменной Т равносильно перечислению в списке всех соответствующих атрибутов, т. е. Т.А1, Т.А2, ..., Т.Аn, где А1, А2,.., Аn — атрибуты отношения, сопоставляемого с переменной Т.
Пример 2. Варианты записи пары <переменная>.<атрибут>.
SX.П#
SX.П# AS Город_Поставщика
SX
SX.П# , SХ.Город_П AS Город_Поставщика, РХ.Д#, РХ.Город_Д# AS Город_Детали
В приведенном определении wff <условие> представляет собой либо формулу wff, заключенную в скобки, либо простое сравнение вида:
<операнд1> Q <операнд2>,
где в качестве любого операнда выступает переменная или скалярная константа, а символ Q обозначает операцию сравнения =, ?ь, >, >, <, < и т. д.
Ключевые слова NOT, AND и OR обозначают логические операции соответственно: И, НЕ и ИЛИ. Ключевые слова IF и THEN переводятся соответственно «если» и «то». И, наконец, ключевые слова EXISTS и FORALL называются кванторами. Первый из них — квантор существования, а второй,— квантор всеобщности. Рассмотрим эти кванторы несколько подробнее.
Формула wff вида: EXISTS x (f) означает: "Существует по крайней мере одно такое значение переменной x, что вычисление формулы f дает значение истина". Выражение вида: FORALL x(f) интерпретируется как высказывание: "Для всех значений переменной х вычисление формулы f дает значение истина". В общем случае переменные кортежей в формулах могут быть свободными или связанными. В формулах EXISTS х (f) и FORALL х (f) переменные кортежей х всегда являются связанными.
Пример 3. Запись выражения.
Приведем запись выражения, соответствующее запросу: "Получить имена поставщиков, которые поставляют все детали".
SX.Город_П WHERE FORALL PX (EXISTS SPX (SPX.П# = SX.П# AND SРХ.Д# = SX.Д# ))
Равносильное этому выражение выглядит так:
SХ.Город_П WHERE NOT EXISTS PX (NOT EXISTS SPX
(SPX.П# = SX.П# AND SPX.Д# = SX.Д# ))
Описанное исчисление не обладает вычислительной полнотой, так как не позволяет выполнять вычисления, связанные с обработкой данных в базах. Добавление вычислительных функций в это исчисление можно реализовать путем расширения определения операндов сравнения и элементов целевого списка таким образом, чтобы они допускали использование скалярных выражений с литералами, ссылками на атрибуты и итоговыми функциями. В качестве итоговых могут выступать следующие функции: COUNT (количество), SUM (сумма), AVG (среднее), МАХ (максимальное), MIN (минимальное). Для целевых элементов целесообразно использовать спецификацию вида "AS <имя атрибута>", позволяющую явно задать имя результирующему атрибуту, если нет очевидного наследуемого имени.
Пример 4. Запись запроса.
Пусть требуется получить информацию о каждой поставке с полными данными о деталях и общем весе поставки. Запрос на дополненном функциями языке реляционного исчисления кортежей может выглядеть следующим образом:
(SPX.П#, SPX.Количество, PX, PX.Bec * SPX. Количество AS Общий_Вес) WHERE PX Д# = SPX.Д#
Вариант реляционного исчисления, основанного на доменах (исчисление доменов), предложен Лакроиксом и Пиротте (Lacroix and Pirotte), которые также разработали на его основе соответствующий язык ILL. Другими языками, основанными, на исчислении доменов, являются: FQL, DEDUCE, а также QBE с некоторыми оговорками.
По утверждению Дейта, язык QBE включает элементы исчисления кортежей и исчисления доменов, но более близок ко второму. Он не является реляционно полным, так как не поддерживает операцию отрицания квантора существования (NOT EXISTS). Несмотря на этот недостаток, язык QBE получил широкое распространение в современных СУБД. Тем более, что реализации этого языка как правило шире исходного языка.
Исчисление доменов имеет много сходства с исчислением кортежей. В отличие от исчисления кортежей, в исчислении доменов основой любого выражения запроса выступают переменные доменов. Переменная домена — это скалярная переменная, значения которой охватывают элементы некоторого домена.
Большая часть различий рассматриваемых исчислений заключается в том, что исчисление доменов поддерживает дополнительную форму условия, называемую условием принадлежности. В общем виде условие принадлежности записывается в виде:
R(A,: A,: ,...),
где А^ — атрибут отношения R, а и — переменная домена или литерал. Проверяемое условие истинно, если и только если существует кортеж в отношении R, имеющий атрибуты А, равные заданным в выражении соответствующим значениям
Например, выражение SP (П# : 'S1', Д# : 'Р1') истинно, если в отношении SP существует хотя бы один кортеж со значением 'S1' атрибута П# и значением 'РГ' атрибута Д#. Аналогично, выражение SP (П# : SX, Д# : РХ) истинно, если в отношении SP существует кортеж, в котором значение атрибута П# эквивалентно текущему значению переменной домена SX, а значение атрибута Д# эквивалентно текущему значению переменной домена РХ.
В следующих примерах будем подразумевать существование (объявленное каким-либо образом, подобно оператору RANGE исчисления кортежей) следующих переменных доменов: SX (домен П#), РХ (домен Д#), NAMEX (домен Имя).
Пример 5. Выражения исчисления доменов.
(SX) WHERE S (П# : SX)
(SX) WHERE S (П# : SX, Город_П : 'Москва')
NAMEX WHERE EXISTS SX ( S (П# : SX, Имя : NAMEX) AND FORALL РХ ( IF P (Д# : РХ ) THEN SP (П# :SX, Д# : РХ ) ) )
Первое выражение означает множество всех номеров поставщиков отношения S, второе — множество номеров поставщиков из Москвы. Третье выражение соответствует запросу на получение имен поставщиков, производящих все детали.
Реляционная алгебра.
Примеры.
Посмотрим, как работают операции реляционной алгебры для другого примера. Возьмем набор отношений, которые моделируют сдачу сессии студентами некоторого учебного заведения.
R1 = <ФИО, Дисциплина, Оценка>; R2 = <ФИО, Группа>; R3 = < Группа, Дисциплина>,
где R1 — информация о попытках (как успешных, так и неуспешных) сдачи экзаменов студентами; R2 — состав групп; R3 — список дисциплин, которые надо сдавать каждой группе. Домены для атрибутов формально задавать не будем, но, ориентируясь на здравый смысл, будем считать, что доменом для атрибута Дисциплина будет множество всех дисциплин, преподающихся в ВУЗе, доменом для атрибута Группа будет множество всех групп ВУЗа и т. д.
Покажем, каким образом можно получить из этих таблиц интересующие нас сведения с помощью реляционной алгебры. В каждом из приведенных примеров путем операций над исходными отношениями R1, R2, R3 формируются промежуточные отношения и результирующее отношение S, содержащее требуемую информацию.
Список студентов, которые сдали экзамен по БД на «отлично». Результат может быть получен применением операции фильтрации по сложному условию к отношению R1 и последующей проектцией на атрибут «ФИО» (нам ведь требуется только список фамилий).
S := (R1 WHERE Оценкa = «5» AND Дисциплина = «БД»)[ФИО];
Список тех, кто должен был сдавать экзамен по БД, но пока еще не сдавал. Сначала найдем всех, кто должен был сдавать экзамен по БД. В отношении R3 находится список всех дисциплин, по которым каждая группа должна была сдавать экзамены, ограничим перечень дисциплин только «БД». Для того чтобы получить список студентов, нам надо соединить отношение R3 с отношением R2, в котором определен список студентов каждой группы.
R4 := ((R2 R3) WHERE R3.Группа = R2.Группа AND R3.Дисциплина = «БД»)[ФИО];
Теперь получим список всех, кто сдавал экзамен по «БД» (нас пока не интересует результат сдачи, а интересует сам факт попытки сдачи, то есть присутствие в отношении R1):
R5 := (R1 WHERE Дисциплина = «БД»)[ФИО];
и, наконец, результат — все, кто есть в первом множестве, но не во втором:
S := R4 \ R5;
Список студентов, имеющих несколько двоек по различным дисциплинам:
S := (R1
R1’) WHERE
R1.ФИО =
R1’.ФИО
AND
R1.Дисциплина
R1’.Дисциплина
AND R1.Оценка
< 2 AND
R1’.Оценка
< 2) [ФИО]
Этот пример весьма интересен: для поиска строк, удовлетворяющих в совокупности условию больше одного, применяется операция соединения отношения с самим собой. Поэтому мы как бы взяли копию отношения R1 и назвали ее R1’.
Список круглых отличников. Строим список всех пар <студент—дисциплина>, которые в принципе должны быть сданы:
R6 := ((R2 R3) WHERE R2.Группа = R3.Группа)[ФИО, Дисциплина];
Строим список пар <студент—дисциплина>, где получена оценка «отлично»:
R7 := (R1 WHERE Оценка = «5»)[ФИО, Дисциплина];
Строим список студентов, что-либо не сдавших на «отлично»:
R8 := (R6 \ R7)[ФИО].
Наконец, исключив последнее отношение из общего списка студентов, получаем результат:
S := R2[ФИО] \ R8
Обратите внимание, что для получения множества студентов, что-либо не сдавших на «отлично» (R8), мы осуществили «инверсию» множества всех отлично сданных пар <студент—дисциплина> (R5) путем вычитания его из предварительного построенного универсального множества (R4). Рекомендуем очень внимательно разобрать этот пример и вникнуть в смысл каждого действия — это очень пригодится для понимания реляционной алгебры.
Задания для самостоятельной работы
Задание 1
Даны отношения, моделирующие работу банка и его филиалов. Клиент может иметь несколько счетов, при этом они могут быть размещены как в одном, так и в разных филиалах банка. В отношении R1 содержится информация обо всех клиентах и их счетах в филиалах нашего банка. Каждый клиент, в соответствии со своим счетом, может рассчитывать на некоторый кредит от нашего банка, сумма допустимого кредита также зафиксирована.
R1
|
||||
ФИО клиента
|
№ филиала
|
№ счета Кредит
|
Остаток
|
Кредит
|
|
|
|
|
|
|
|
|||
R2
|
||||
№ филиала
|
Район
|
|||
|
|
|||
С использованием языка реляционной алгебры составить запросы, позволяющие выбрать:
1. Филиалы, клиенты которых имеют счета с остатком, превышающим $1000.
S := (R1 WHERE Остаток > 1000) [№ филиала]
2. Клиентов, которые имеют счета во всех филиалах данного банка.
R3 := R2 [№ филиала]
R4 := R1 [ФИО, № филиала]
S := R4 DIVIDEBY R3
3. Клиентов, которые имеют только по одному счету в разных филиалах банка. То есть, в общем, у этих клиентов может быть несколько счетов, но в одном филиале не более одного счета.
R3 := (R1 R1’) WHERE R1.ФИО = R1’.ФИО AND R1. № филиала = R1’.№ филиала AND R1.№ счета R1’.№ счета) [ФИО]
R4 := R1 [ФИО]
S := R4 \ R3
4. Клиенты, которые имеют счета в нескольких филиалах банка, расположенных только в одном районе.
R3 := (R1 R1’) WHERE R1.ФИО = R1’.ФИО AND R1. № филиала = R1’.№ филиала) [ФИО]
??
5. Филиалы, которые не имеют ни одного клиента.
R3 := R2 [№ филиала] – все филиалы
R4 := R1 [№ филиала] – все филиалы, в которых есть клиенты
S := R4 \ R3
6. Филиалы, которые имеют клиентов с остатком на счету 0 (ноль).
S := (R1 WHERE Остаток = 0) [№ филиала]
7. Филиалы, у которых есть клиенты с кредитом, превышающим остаток на счету в 2 раза.
S := (R1 WHERE Кредит > 2*Остаток) [№ филиала]
Задание 2
Даны отношения, моделирующие работу международной фирмы, имеющей несколько филиалов. Филиалы фирмы могут быть расположены в разных странах, это отражено в отношении R1. Клиенты фирмы также могут быть из разных стран, и это отражено в отношении R4. По каждому конкретному заказу клиент мог заказать несколько разных товаров.
R1
|
|
||||
Филиал
|
Страна
|
|
|||
|
|
|
|||
|
|
|
|||
R2
|
|||||
Филиал
|
Заказчик
|
№ заказа
|
|||
|
|
|
|||
|
|
|
|||
R3
|
|||||
N заказа
|
Товар
|
Количество
|
|||
|
|
|
|||
|
|
|
|||
R4
|
|
||||
Заказчик |
Страна
|
|
|||
|
|
|
|||
С использованием реляционной алгебры составить запросы, позволяющие выбрать:
1. Заказчиков, которые работают со всеми филиалами фирмы, но покупают только один товар.
2. Филиалы фирмы, которые торгуют всеми товарами.
3. Товары, которые фирма продает только в одной стране.
4. Заказчиков, которые работают с филиалами фирмы, которые расположены только в одной стране.
5. Филиалы, с которыми не работает ни один заказчик.
6. Заказчиков, которые работают только с филиалами, расположенными в той же стране, что и заказчик.
7. Заказчиков, которые покупают все товары, представленные в отношении Кз.
Задание 3
Даны отношения, моделирующие работу фирмы, занимающейся разработкой программных систем. Каждый сотрудник административно закреплен только за одним отделом. Файлы хранятся на разных серверах. На разных серверах файлы могут иметь одинаковые имена. Создатель файла является его владельцем, поэтому у каждого файла только один владелец, но владелец файла может разрешить пользоваться файлом другим сотрудникам. Существует множество системного программного обеспечения, каждая программа может работать с одним или с несколькими файлами, расположенными на одном или нескольких серверах:
R.
|
R4
|
||
Название файла
|
Имя владельца файла
|
Сотрудник Отдел
|
|
|
|
|
|
|
|||
R2
|
|||
Название программы
|
Название файла
|
Сервер
|
|
|
|
|
|
|
|
||
R,3
|
|||
Название файла
|
Название сервера
|
||
'
|
|
||
С использованием реляционной алгебры и языка составить запросы, позволяющие выбрать:
1. Файлы, которые имеют нескольких пользователей из разных отделов.
2. Программы, которые работают только с одним файлом.
3. Файлы, которые имеют одно и тоже имя, но расположены на различных серверах и используются сотрудниками разных отделов.
4. Файлы, с которыми работают сотрудники всех отделов.
5. Файлы, пользователями которых являются сотрудники только одного отдела.
6. Программы, которые работают со всеми серверами.
7. Отделы, сотрудники которых не работают ни с одним файлом. То есть отделы, в которых нет ни одного сотрудника, работающего с каким-нибудь файлом.
8. Отделы, сотрудники которых работают со всеми серверами.
Серверы, с которыми работают сотрудники только одного отдела.
