русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Об'єднання таблиць


Дата добавления: 2015-07-09; просмотров: 1088; Нарушение авторских прав


Вище було показано, що в багатотабличному запиті можна поєднувати дані таблиць, однак цікаво й те, що та ж сама методика може використовуватись для об'єднання разом двох копій одиночної таблиці. Для об'єднання таблиці із собою можна зробити кожен рядок таблиці одночасно й комбінацією її із собою й комбінацією з кожним іншим рядком таблиці, а потім оцінити кожну комбінацію в термінах предиката. Це дозволяє легко створювати певні види зв'язків між різними елементами усередині одиночної таблиці. Наприклад, допускається зобразити об'єднання таблиці із собою, як об'єднання двох копій однієї й тієї ж таблиці, причому вона насправді не копіюється, але SQL виконує команду так, ніби це було зроблено.

Використання команди для об'єднання таблиці із собою аналогічно тому прийому, що використовується для об'єднання декількох таблиць. Коли поєднується таблиця із собою, всі повторювані імена стовпця заповнюються префіксами імені таблиці. Щоб посилатися до цих стовпців усередині запиту, необхідно мати два різних імена для цієї таблиці. Це можна зробити за допомогою визначення тимчасових імен, що називаються псевдонімами, які визначаються в команді FROM запиту. Синтаксис у цьому випадку наступний: після імені таблиці залишають пробіл, а потім повинен йти псевдонім для неї.

Наприклад, для пошуку студентів, що мають однаковий розмір стипендії, можна скористатися наступним запитом:

SELECT FIRST.SFAM, SECOND.SFAM, FIRST.STIP

FROM STUDENTS FIRST, STUDENTS SECOND

WHERE FIRST.STIP = SECOND.STIP;

Результат такого запиту буде наступний:

--------------------------------------------------

Поляков Поляков 25.50

Поляков Нагорний 25.50

Старова Старова 7.00

Гриценко Гриценко 0.00

Гриценко Котенко 0.00

Котенко Гриценко 0.00

Котенко Котенко 0.00

Нагорний Поляков 25.50

Нагорний Нагорний 25.50



 

У даному прикладі SQL поводиться так, ніби вона з'єднувала дві різні таблиці, з назвами FIRST й SECOND, тобто псевдоніми дозволяють одній й тій же таблиці бути опрацьованою незалежно. Зверніть увагу на те, що псевдоніми можуть використовуватись в команді SELECT до їхнього оголошення в команді FROM, однак SQL буде спочатку допускати будь-які псевдоніми й може відхилити команду, якщо вони не будуть визначені далі в запиті. Крім того, необхідно пам'ятати, що псевдонім існує тільки тоді, коли команда виконується, а після завершення запиту псевдоніми, використовувані в ньому більше не мають ніякого значення.

Вивід останнього прикладу має два значення для кожної комбінації прізвищ, причому другий раз у зворотному порядку - це пов'язане з тим, що кожне значення показане перший раз у кожному псевдонімі й другий раз у предикаті, тобто поточне значення в першому псевдонімі спочатку вибирається в комбінації зі значенням у другому псевдонімі, а потім навпаки. Наприклад, у нашому випадку Поляков вибрався разом з Нагорним, а потім Нагорний вибрався разом з Поляковым і т.д. Крім того, кожен рядок був зрівняний сама із собою, наприклад Поляков з Поляковым.

Кращий спосіб уникнути цього полягає в накладанні порядку на два значення так, щоб один міг бути менше, ніж інший або передував йому за абеткою. Це робить предикат асиметричним щодо зв'язку, тому ті ж самі значення у зворотному порядку не будуть обрані знову. Отже, приклад можна модифікувати в такий спосіб:

SELECT FIRST.SEAM, SECOND. SFAM, FIRST.STIP

FROM STUDENTS FIRST, STUDENTS SECOND

WHERE FIRST.STIP = SECOND.STIP

AND FIRST.SFAM < SECOND.SFAM;

Результат цього запиту буде такою:

--------------------------------------------------

Гриценко Котенко 0.00

Нагорний Поляков 25.50

 

Зокрема, Гриценко передує Котенко за абеткою, тому комбінація задовольняє обом умовам предиката й з'являється у висновку. Якщо та ж сама комбінація з'являється у зворотному порядку, тобто Котенко в псевдонімі першої таблиці рівняється із Гриценко в другій таблиці, то друга умова не виконується. З аналогічної причини у висновок не попадає порівняння із самим собою. Якщо ж виникла необхідність порівняння рядків з ними ж, то в запитах варто використати < = замість <

Таким чином, можна використати цю особливість SQL для перевірки певних видів помилок. Наприклад, якщо вважати, що навчальний предмет може вести тільки один викладач, те щораз у таблиці PREDMET необхідна перевірка на цю умову. При цьому щораз, коли код предмета з'являється в таблиці PREDMET, він повинен збігатися з відповідним номером викладача. Наступна команда буде визначати будь-які неузгодженості в цій області:

SELECT FIRST.PNUM, FIRST.TNUM,

SECOND.PNUM, SECOND.TNUM

FROM PREDMET FIRST, PREDMET SECOND

WHERE FIRST.PNUM - SECOND.PNUM

AND FIRST. TNUM <> SECOND. TNUM;

Виводу для даного приклада не буде, тому що даних, що задовольняють предикату в розглянутій таблиці немає. Логіка цього запиту досить проста: з таблиці буде вибиратися черговий рядок і запам'ятовуватися під першим псевдонімом. Після цього SQL почне перевіряти її в комбінації з кожним рядком таблиці під другим псевдонімом. Якщо комбінація рядків задовольняє предикату, то вона вибирається для висновку, тобто якщо буде знайдений навчальний предмет, у якого з'ясується розбіжність номера викладача в таблиці під першим і другим псевдонімом.

Об'єднання таблиці із собою - це найбільше що часто зустрічається ситуація, коли використаються псевдоніми, однак їх можна використати в будь-який час для створення альтернативних імен для таблиць у запиті, наприклад, у випадку, якщо таблиці мають дуже довгі й складні імена.

Більше того, допускається використати будь-яке число псевдонімів для однієї таблиці в запиті, хоча використання більше двох в одній пропозиції SELECT часто буде надмірністю. Наприклад, для призначення стипендії на наступний семестр необхідно переглянути всі варіанти комбінацій студентів з різними розмірами стипендії: 25.50, 17.00 й 0.00 у.е. Тоді такий запит буде виглядати в такий спосіб:

SELECT FIRST.SFAM, SECOND.SFAM, THIRD.SFAM

FROM STUDENTS FIRST, STUDENTS SECOND,

STUDENTS THIRD

WHERE FIRST.STIP = 25.50

AND SECOND.STIP = 17.00

AND THIRD.STIP = 0.00;

Результат виконання для цього запиту записаний нижче:

SFAM SFAM SFAM

-----------------------------------------------------

Поляков Старова Гриценко

Поляков Старова Котенко

Нагорний Старова Гриценко

Нагорний Старова Котенко

Як видно з результату, цей запит знаходить всі комбінації студентів із трьома різними розмірами стипендії, тому перший стовпець висновку складається зі студентів зі стипендією 25.50, другий з 17.00 й останній - з 0.00, які повторюються у всіх можливих комбінаціях. Цікаво, що такий запит не може бути виконаний з GROUP BY або ORDER BY, оскільки вони порівнюють значення тільки в одному стовпці висновку.

У команді SELECT допускається не використати кожен псевдонім або таблицю, які згадувалися в пропозиції FROM запиту, тобто псевдонім або таблиця використаються тільки для створення предиката. Розглянемо чисто ілюстративний приклад наступного запиту:

SELECT FIRST.SFAM, FIRST.SIMA, FIRST.SOTCH

FROM STUDENTS FIRST, STUDENTS SECOND

WHERE FIRST.STIP = 25.50

AND SECOND.STIP = 0.00;

Результат даного запиту наступний:

SFAM SIMA SOTCH

------------------------------------------------------------

Поляков Анатолій Олексійович

Поляков Анатолій Олексійович

Нагорний Євген Васильович

Нагорний Євген Васильович

Фактично тут дані про студентів, що мають стипендію 25.50, повторюються стільки разів, скільки існує їхніх сполучень зі студентами, що не одержують стипендію (тобто для яких STIP = 0.00).

В SQL передбачається створення об'єднання, що включає й різні таблиці, і псевдоніми одиночної таблиці. Наступний запит поєднує таблицю з даними про успішність для того, щоб знайти навчальні предмети, які вже здані більш ніж одним студентом, і таблицю навчальних предметів:

SELECT PREDMET . PNAME , FIRST.SNUM,

SECOND.SNUM

FROM USP FIRST, USP SECOND, PREDMET

WHERE FIRST.PNUM = SECOND.PNUM

AND PREDMET.PNUM = FIRST.PNUM

AND FIRST.SNUM < SECOND.SNUM;

Результати цього запиту наступні:

PNAME SNUM SNUM

------------------------------------------------------

Математика 3413 3412

У виводі маємо пари номерів студентів, що здали той або інший предмет, що визначається за назвою з таблиці навчальних предметів.

Як уже було сказано, операція об'єднання в SQL з'єднує інформацію із двох таблиць, формуючи пари зв'язаних рядків з них. Об'єднану таблицю утворять пари тих рядків з різних таблиць, в яких у зв'язаних стовпцях знаходяться однакові значення. Якщо рядок однієї з таблиць не має пари, то об'єднання може привести до несподіваних результатів.

Припустимо, що в таблиці TEACHERS з'явився запис {NULL, Федченко, Світлана, Геннадіївна, 01/09/1999}, у якій табельний номер ще не відомий. Несподівані результати можуть вийти при використанні наступних запитів:

SELECT TFAM, TIMA, ТОТСН

FROM TEACHERS

Результат цього запиту наступний:

TFAM TIMA ТОТСН

---------------------------------------------------------------

Викулина Валентина Іванівна

Костыркин Олег Володимирович

Казанко Віталій Володимирович

Позднякова Любов Олексіївна

Загарийчук Ігор Дмитрович

Федченко Світлана Геннадіївна

і запиту

SELECT TEACHERS.TFAM, PREDMET.PNAME

FROM TEACHERS, PREDMET

WHERE TEACHERS . TNUM = PREDMET.TNUM;

Вивід цього запиту такий:

TFAM PNAME

------------------------------------------

Викулина Фізика

Костыркин Хімія

Казанко Математика

Позднякова Економіка

Загарийчук Філософія

Здавалося б, що ці два запити повинні давати однакову кількість рядків, але результати першого запиту нараховують шість рядків, а другого - тільки п'ять. Це пов'язане з тим, що викладач Федченко в даний момент ще не одержала номер й відповідний запис має значення NULL у поле TNUM, отже, це значення не збігається з жодним ідентифікатором навчального предмета в таблиці PREDMET. Виходить, виводу цього рядка в другому запиті не буде - він просто зникає з об'єднання. Таким чином, стандартне SQL-об'єднання може привести до втрати інформації, якщо поєднувані таблиці містять незв'язані рядки.

Другий запит можна модифікувати в такий спосіб:

SELECT TEACHERS.TFAM, PREDMET. PNAME

FROM TEACHERS, PREDMET

WHERE TEACHERS . TNUM *= PREDMET. TNUM;

і його вивід буде більше повний:

TFAM PNAME

-----------------------

Никулина Фізика

Костыркин Хімія

Казанко Математика

Позднякова Економіка

Загарийчук Філософія

Федченко NULL

Такі результати запиту виходять за допомогою іншої операції об'єднання, називаної зовнішнім об'єднанням таблиць, що у команді WHERE позначається символом *=. Зовнішнє об'єднання є розширенням стандартного об'єднання, описаного вище й іноді називаного внутрішнім об'єднанням таблиць. Майте на увазі, що в стандарті SQL1 дане визначення тільки внутрішнього об'єднання, а поняття зовнішнього об'єднання в ньому відсутній.

Розглянемо повне зовнішнє об'єднання таблиць на прикладі наступного запиту:

SELECT STUDENTS.SFAM, STUDENTS.SNUM,

USP.PNUM, USP.SNUM

FROM STUDENTS, USP

WHERE STUDENTS.SNUM = USP.SNUM;

Результат цього запиту наведений нижче:

SFAM SNUM PNUM SNUM

-----------------------------------------------------

Поляков 3412 2001 3412

Поляков 3412 2003 3412

Огарьова 3413 2003 3413

Гриценко 3414 2005 3414

Нагорний 3416 2004 3416

Цей запит формує інформацію про студентів і коди навчальних предметів, які ними здані. Це внутрішнє об'єднання дає п'ять рядків виводу, показуючи відповідні пари студент - код предмета. Для студента Котенко ніякого висновку ні, оскільки він ніяких дисциплін не здавав.

Тепер припустимо, що необхідно вивести ту ж інформацію, але з урахуванням студентів, яким не відповідає жоден навчальний предмет. Такий запит, побудований за правилами повного зовнішнього об'єднання, буде виглядати так:

SELECT STUDENTS.SFAM, STUDENTS.SNUM,

USP.PNUM, USP.SNUM

FROM STUDENTS, USP

WHERE STUDENTS.SNUM *=* USP.SNUM;

Результат цього запиту такий:

SFAM SNUM PNUM SNUM

-----------------------------------------------------

Поляков 3412 2001 3412

Поляков 3412 2003 3412

Старова 3413 2003 3413

Гриценко 3414 2005 3414

Котенко 3415 NULL NULL

Нагорний 3416 2004 3416

У цей вивід потрапили рядка зі значеннями NULL, тобто запис для студента Котенко був як би прив'язан до неіснуючого рядка таблиці USP, що містить тільки значення NULL, і доданий в результат запиту. Як видно із цього прикладу, зовнішнє об'єднання є таким що зберігає інформацію й кожен рядок таблиці - операнда представлена у висновку результатів запиту. Отже, повне зовнішнє об'єднання таблиць виходить із внутрішнього об'єднання двох таблиць звичайним способом, при цьому кожен запис першої таблиці, що не має зв'язку з жодною рядком у другій таблиці, доповнюється в результатах запиту значеннями NULL. У той же час, кожен рядок другої таблиці, що не має зв'язку з жодною рядком першої таблиці, доповнюється в результатах запиту значеннями NULL.

Існують ще так звані ліве й праве зовнішні об'єднання. Якщо повне зовнішнє об'єднання симетрично стосовно обох таблицям-операндам, то ці два типи зовнішніх об'єднань не симетричні щодо двох таблиць.

Ліве зовнішнє об'єднання двох таблиць записується в команді WHERE у вигляді *= і отримується в результаті виконання внутрішнього об'єднання таблиць. При цьому відбуваються дії, аналогічні повному об'єднанню, однак без заміни NULL значеннями інформації, взятої із другої таблиці. Приклад лівого зовнішнього об'єднання фактично нами вже був розглянутий вище в прикладі для викладачів і предметів.

Праве зовнішнє об'єднання двох таблиць записується в команді WHERE у вигляді =* і отримується із звичайного внутрішнього об'єднання таблиць у послідовності реалізації повного об'єднання, при цьому заміна на NULL значення в першій таблиці не відбувається.

На практиці лівого й праве зовнішні об'єднання більше корисні, чим повне зовнішнє об'єднання, особливо при зв'язку таблиць через ключі. Система запису зовнішнього об'єднання дозволяє використати не тільки знак рівності, але й інші знаки відносин. Наприклад, допустимо наступний запит, що представляє, по суті, ліве зовнішнє об'єднання:

SELECT STUDENTS.SFAM, STUDENTS.SNUM,

USP.PNUM, USP.SNUM

FROM STUDENTS, USP

WHERE STUDENTS.SNUM *> USP.SNUM;

Результат цього запиту, наведений не повністю через його значні розміри, буде наступний:

SFAM SNUM PNUM SNUM

--------------------------------------------------

Поляков 3412 NULL NULL

Старова 3413 2001 3412

Старова 3413 2003 3412

Гриценко 3414 2001 3412

Гриценко 3414 2003 3412

Гриценко 3414 2003 3413

 

Даний запит виводить інформацію про студентів і про здані навчальні предмети, при цьому дані про предмети вибираються для студентів номер яких менше, ніж поточний. У випадку, якщо таких не виявляється, SQL формує рядок з першої таблиці, заповнюючи NULL значеннями дані, які повинні були бути отримані із другої.

Хоча система запису зовнішнього об'єднання досить зручна, вона має свої недоліки. Справа в тому, що проблеми із записом зовнішніх об'єднань виникають при розширенні об'єднання до трьох або більше таблиць. Наприклад, при записі

TABLE1 *=* TABLE2 *=* TABLE3

фактично виконується зовнішнє об'єднання

(TABLE1 *=* TABLE2) *=* TABLE3

що, загалом кажучи, призведе до різних результатів.

Для розробників стандарту SQL2 зовнішні об'єднання були серйозною проблемою, тому що зовнішні об'єднання є часом єдиним способом надання результатів ряду вкрай необхідних запитів. Тому в стандарті SQL2 був визначений зовсім новий метод підтримки зовнішніх об'єднань: у специфікації стандарту SQL2 підтримка зовнішніх об'єднань здійснюється в команді FROM зі спеціальним синтаксисом, що дозволяє користувачеві точно визначити, як вихідні таблиці повинні бути об'єднані в запиті.

Наприклад, уже розглянутий нами запит внутрішнього об'єднання в стандарті SQL1 виглядає так:

SELECT STUDENTS.SFAM, STUDENTS.SNUM,

USP.PNUM-, USP.SNUM

FROM STUDENTS, USP

WHERE STUDENTS.SNUM = USP.SNUM;

а в стандарті SQL2 - так (хоча використання першого варіанта допускається):

SELECT STUDENTS.SFAM, STUDENTS.SNUM,

USP.PNUM, USP.SNUM

FROM STUDENTS INNER JOIN USP

ON STUDENTS . SNUM = USP.SNUM;

Зверніть увагу на те, що в останньому випадку дві поєднувані таблиці з'єднуються явно за допомогою операції JOIN, а умова пошуку, що описує об'єднання, перебуває тепер у команді ON усередині команди FROM. В умові пошуку, що розміщена за ключовим словом ON, можуть бути задані будь-які критерії порівняння рядків двох поєднуваних таблиць, у тому числі з використанням булевих операторів.

Нарешті, приведемо приклад повного зовнішнього об'єднання (аналогічний запит був уже розглянутий):

SELECT STUDENTS.SFAM, STUDENTS.SNUM,

USP.PNUM, USP.SNUM

FROM STUDENTS FULL OUTER JOIN USP

ON STUDENTS.SNUM = USP.SNUM;

Його результати наведені нижче:

SFAM SNUM PNUM SNUM

-----------------------------------------------------

Поляков 3412 2001 3412

Поляков 3412 2003 3412

Огарьова 3413 2003 3413

Гриценко 3414 2005 3414

Котенко 3415 NULL NULL

Нагорний 3416 2004 3416

Таким чином, у цих двотабличних об'єднаннях все вмістиме команди WHERE просто перейшло в команду ON, отже, нічого принципово нового ON не додає в мову SQL. Однак така структура дозволяє більш точно визначити умову об'єднання.



<== предыдущая лекция | следующая лекция ==>
Особливості багатотабличних запитів | Використання вкладених запитів


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 4.089 сек.