Структуризувати мову запитів (sql)

Глава 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 Первая.Блюдо <Вторая.Блюдо;