Глава 3. Запити з використанням декількох таблиць
У літературі показано, що сполуки - це підмножини декартового добутку. Так як декартовій твір n таблиць - це таблиця, яка містить всі можливі рядки r, такі, що r є зчепленням будь-якої рядки з першої таблиці, рядки з другої таблиці. і рядки з n-й таблиці (а ми вже навчилися виділяти за допомогою SELECT будь-яка підмножина реляційної таблиці), то залишилося лише з'ясувати, чи можна за допомогою SELECT отримати декартовій твір. Для отримання декартова твори кількох таблиць треба вказати у фразі FROM перелік перемножуєте таблиць, а у фразі SELECT - все їх стовпці.
Так, для отримання декартова твори Від_блюд і Трапези треба видати запит
SELECT Від_блюд. *, Трапези. *
FROM Від_блюд, Трапези;
Отримаємо таблицю, яка містить 5 х 3 = 15 рядків:
SELECT Меню. *, Трапези. *, Від_блюд. *, Страви. *
FROM Меню, Трапези, Від_блюд, Страви;
утворюється таблиця (рис 3.1), що містить 21 х 3 х 5 х 33 = 10395 рядків.
З перших 39 рядків цієї таблиці лише дві актуальних (відзначені "*"): в них збігаються номери страв таблиць Меню і Блюда. В інших - повна нісенітниця: до закусок віднесені супи і напої, на сніданок пропонується незапланований суп і т.д.
Якщо з декартова твори прибрати непотрібні рядки і стовпці, то можна отримати актуальні таблиці, відповідні будь-якому із з'єднань.
Мал. 3.1. Ілюстрація декартова твори
Очевидно, що відбір актуальних рядків забезпечується введенням в запит WHERE фрази, в якій встановлюється відповідність між:
- кодами трапез (Т) в таблицях Меню і Трапези (Меню.Т = Трапези.Т),
- кодами видів страв (В) в таблицях Меню і Від_блюд (Меню.В = Від_блюд.В),
- номерами страв (БЛ) в таблицях Меню і Блюда (Меню.БЛ = Блюда.БЛ).
Такий скоригований запит
SELECT Меню. *, Трапези. *, Від_блюд. *, Страви. *
FROM Меню, Трапези, Від_блюд, Страви
WHERE Меню.Т = Трапези.Т
AND Меню.В = Від_блюд.В
AND Меню.БЛ = Блюда.БЛ;
дозволить отримати еквісоедіненія таблиць Меню, Трапези, Від_блюд і Страви:
М'ясо з гарніром
Легко помітити, що в еквісоедіненія таблиць увійшли дублікати стовпців, за якими проводилося з'єднання (Т, У і БЛ). Для виключення цих дублікатів можна створити природне з'єднання тих же таблиць:
SELECT Т, У, БЛ, Трапеза, Вид, Блюдо, Основа, Вихід, Праця
FROM Меню, Трапези, Від_блюд, Страви
WHERE Меню.Т = Трапези.Т
AND Меню.В = Від_блюд.В
AND Меню.БЛ = Блюда.БЛ;
Реалізація природного з'єднання таблиць має вигляд
М'ясо з гарніром
Для виключення всіх стовпців, по яких проводиться з'єднання таблиць, треба створити композицію
SELECT Трапеза, Вид, Блюдо, Основа, Вихід, Праця
FROM Меню, Трапези, Від_блюд, Страви
WHERE Меню.Т = Трапези.Т
AND Меню.В = Від_блюд.В
AND Меню.БЛ = Блюда.БЛ;
М'ясо з гарніром
У базі даних ПАНСІОН важко підібрати нескладний приклад, який ілюструє тета-з'єднання таблиць. Тому сконструюємо такий надуманий запит:
SELECT Від_блюд. *, Трапези. *
FROM Від_блюд, Трапези
WHERE Вид> Трапеза;
дозволяє вибрати з отриманого в п.3.2.1 декартова твори таблиць Від_блюд і Трапези лише ті рядки, в яких значення трапези "менше" (за алфавітом) значення виду страви
При формуванні з'єднання створюється робоча таблиця, до якої застосовні всі операції, розглянуті в главі 2: відбір потрібних рядків з'єднання (WHERE фраза), впорядкування одержуваного результату (ORDER BY фраза) і агрегатування даних (SQL-функції і GROUP BY фраза).
Наприклад, для отримання переліку страв, пропонованих в меню на сніданок, можна сформувати запит на основі композиції (п. 3.2.4):
SELECT Вид, Блюдо, Основа, Вихід, 'Номер -', БЛ
FROM Меню, Трапези, Від_блюд, Страви
WHERE Меню.Т = Трапези.Т
AND Меню.В = Від_блюд.В
AND Меню.БЛ = Блюда.БЛ
AND Трапеза = 'Сніданок';
М'ясо з гарніром
В п.3.6 можна познайомитися з досить повним прикладом з'єднання таблиць з різними додатковими фразами.
У ряді програм виникає необхідність одночасної обробки даних будь-якої таблиці і однієї або декількох її копій, створюваних на час виконання запиту.
Наприклад, щоб створити список студентів (таблиця Студенти) можливий повторний введення даних про будь-якому студентові з присвоєнням йому другого номера залікової книжки. Для виявлення таких помилок можна з'єднати таблицю Студенти з її тимчасової копією, встановивши в WHERE фразі рівність значень всіх однойменних стовпців цих таблиць крім стовпців з номером залікової книжки (для останніх треба встановити умову нерівності значень).
Тимчасову копію таблиці можна сформувати, вказавши ім'я псевдоніма за ім'ям таблиці у фразі FROM. Так, за допомогою фрази
FROM Страви X, Страви Y, Страви Z
будуть сформовані три копії таблиці Страви з іменами X, Y і Z.
Як приклад з'єднання таблиці з нею самою сформуємо запит на висновок таких пар страв таблиці Страви, в яких збігається основа, а назва першої страви пари менше (за алфавітом), ніж номер другої страви пари. Для цього можна створити запит з однією копією таблиці Страви (Копія):
SELECT Страва, Копія.Блюдо, Основа
FROM Страви, Страви Копія
WHERE Основа = Копія.Основа
AND Блюдо <Копия.Блюдо;
або двома її копіями (Перша і Друга):
SELECT Первая.Блюдо, Вторая.Блюдо, Основа
FROM Страви Перша, Страви Друга
WHERE Первая.Основа = Вторая.Основа
AND Первая.Блюдо <Вторая.Блюдо;