Назад в раздел
InfoCity
ДО ЭТОГО, КАЖДЫЙ ЗАПРОС КОТОРЫЙ МЫ ИССЛЕДОВАЛИ основывался на оди-
ночной таблице. В этой главе, вы узнаете как сделать запрос любого
числа таблиц с помощью одной команды. Это - чрезвычайно мощное средс-
тво потому что оно не только объединяет вывод из многочисленых таблиц,
но и определяет связи между ними. Вы обучитесь различным формам кото-
рые могут использовать эти связи, а также устанавливать и использовать
их чтобы удовлетворять возможным специальным требованиям.
Одна из наиболее важных особенностей запросов SQL - это их способ-
ность определять связи между многочислеными таблицами и выводить ин-
формацию из них в терминах этих связей, всю внутри одной команды. Этот
вид операции называется - объединением, которое является одним из ви-
дов операций в реляционных базах данных. Как установлено в Главе 1,
главное в реляционном подходе это связи которые можно создавать между
позициями данных в таблицах. Используя обьединения, мы непосредственно
связываем информацию с любым номером таблицы, и таким образом способны
создавать связи между сравнимыми фрагментами данных. При обьединении,
таблицы представленые списком в предложении FROM запроса, отделяются
запятыми. Предикат запроса может ссылаться к любому столбцу любой свя-
занной таблицы и, следовательно, может использоваться для связи между
ими. Обычно, предикат сравнивает значения в столбцах различных таблиц
чтобы определить, удовлетворяет ли WHERE установленному условию.
Полное имя столбца таблицы фактически состоит из имени таблицы, соп-
ровождаемого точкой и затем именем столбца. Имеются несколько примеров
имен :
Salespeople.snum
Salespeople.city
Orders.odate
До этого, вы могли опускать имена таблиц потому что вы запрашивали
только одну таблицу одновременно, а SQL достаточно интелектуален чтобы
присвоить соответствующий префикс, имени таблицы. Даже когда вы делае-
те запрос многочисленых таблиц, вы еще можете опускать имена таблиц,
если все ее столбцы имеют различные имена. Но это не всегда так быва-
ет. Например, мы имеем две типовые таблицы со столбцами называемыми
city.
Если мы должны связать эти столбцы( кратковременно ), мы будем долж-
ны указать их с именами Salespeople.city или Customers.city, чтобы SQL
мог их различать.
Предположим что вы хотите поставить в соответствии вашему продавцу
ваших заказчиков в городе в котором они живут, поэтому вы увидите все
комбинации продавцов и заказчиков для этого города. Вы будете должны
брать каждого продавца и искать в таблице Заказчиков всех заказчиков
того же самого города. Вы могли бы сделать это, введя следующую коман-
ду ( вывод показывается в Рисунке 8.1 ):
SELECT Customers.cname, Salespeople.sname,
Salespeople.city
FROM Salespeople, Customers
WHERE Salespeople.city = Customers.city;
=============== SQL Execution Log ============
| SELECT Customers.cname, Salespeople.sname, |
| Salespeople.city |
| FROM Salespeople, Customers |
| WHERE Salespeople.city = Customers.city |
| ============================================= |
| cname cname city |
| ------- -------- ---- |
| Hoffman Peel London |
| Hoffman Peel London |
| Liu Serres San Jose |
| Cisneros Serres San Jose |
| Hoffman Motika London |
| Clemens Motika London |
=============================================
Рисунок 8.1: Объединение двух таблиц
Так как это поле city имеется и в таблице Продавцов и таблице Заказ-
чиков, имена таблиц должны использоваться как префиксы. Хотя это необ-
ходимо только когда два или более полей имеют одно и то же имя, в лю-
бом случае это хорошая идея включать имя таблицы в обьединение для
лучшего понимания и непротиворечивости. Несмотря на это, мы будем, в
наших примерах далее, использовать имена таблицы только когда необхо-
димо, так что будет ясно, когда они необходимы а когда нет.
Что SQL в основном делает в обьединении - так это исследует каждую
комбинацию строк двух или более возможных таблиц, и проверяет эти ком-
бинации по их предикатам. В предыдущем примере, требовалась строка
продавца Peel из таблицы Продавцов и объединение ее с каждой строкой
таблицы Пользователей, по одной в каждый момент времени. Если комбина-
ция производит значение которое делает предикат верным, и если поле
city из строк таблиц Заказчика равно London, то Peel - это то запраши-
ваемое значение которое комбинация выберет для вывода. То же самое бу-
дет затем выполнено для каждого продавца в таблице Продавцов ( у неко-
торых из которых небыло никаких заказчиков в этих городах).
Эта особенность часто используется просто для эксплуатации связей
встроенных в базу данных. В предыдущем примере, мы установили связь
между двумя таблицами в обьединении. Это прекрасно. Но эти таблицы,
уже были соединены через snum поле. Эта связь называется состоянием
справочной целостности, как мы уже говорили в Главе 1. Используя обь-
единение можно извлекать данные в терминах этой связи. Например, чтобы
показать имена всех заказчиков соответствующих продавцам которые их
обслуживают, мы будем использовать такой запрос:
SELECT Customers.cname, Salespeople.sname
FROM Customers, Salespeople
WHERE Salespeople.snum = Customers.snum;
Вывод этого запроса показывается в Рисунке 8.2.
Это - пример обьединения, в котором столбцы используются для опреде-
ления предиката запроса, и в этом случае, snum столбцы из обеих таб-
лиц, удалены из вывода. И это прекрасно. Вывод показывает какие заказ-
чики каким продавцом обслуживаются; значения поля snum которые уста-
навливают связь - отсутствуют. Однако если вы введете их в вывод, то
вы должны или удостовериться что вывод понятен сам по себе или обеспе-
чить коментарий к данным при выводе.
=============== SQL Execution Log ============
| SELECT Customers.cname, Salespeople.sname, |
| FROM Salespeople, Customers |
| WHERE Salespeople.snum = Customers.snum |
| ============================================= |
| cname sname |
| ------- -------- |
| Hoffman Peel |
| Giovanni Axelrod |
| Liu Serres |
| Grass Serres |
| Clemens Peel |
| Cisneros Rifkin |
| Pereira Motika |
=============================================
Рисунок 8.2: Объединение продавцов с их заказчикам
Обьединения которые используют предикаты основанные на равенствах
называются - объединениями по равенству. Все наши примеры в этой главе
до настоящего времени, относились именно к этой категории, потому что
все условия в предложениях WHERE базировались на математических выра-
жениях использующих знак равно ( = ). Строки 'city = 'London' и 'Sa-
lespeople.snum = Orders.snum ' - примеры таких типов равенств найден-
ных в предикатах. Объединения по равенству - это вероятно наиболее об-
щий вид объединения, но имеются и другие. Вы можете, фактически, ис-
пользовать любой из реляционных операторов в обьединении. Здесь пока-
зан пример другого вида объединения (вывод показывается в Рисунке
8.3):
SELECT sname, cname
FROM Salespeople, Customers
WHERE sname < cname
AND rating < 200;
=============== SQL Execution Log ============
| SELECT sname, cname |
| FROM Salespeople, Customers |
| WHERE sname < cname |
| AND rating < 200; |
| ============================================= |
| sname cname |
| -------- ------- |
| Peel Pereira |
| Motika Pereira |
| Axelrod Hoffman |
| Axelrod Clemens |
| Axelrod Pereira |
| |
=============================================
Рисунок 8.3: Обьединение основанное на неравенстве
Эта команда не часто бывает полезна. Она воспроизводит все комбина-
ции имени продавца и имени заказчика так, что первый предшествует пос-
леднему в алфавитном порядке, а последний имеет оценку меньше чем 200.
Обычно, вы не создаете сложных связей подобно этой, и, по этой причи-
не, вы вероятно будете строить наиболее общие объединения по равенс-
тву, но вы должны хорошо знать и другие возможности.
Вы можете также создавать запросы объединяющие более двух таблиц.
Предположим что мы хотим найти все порядки заказчиков не находящихся в
тех городах где находятся их продавцы.Для этого необходимо связать все
три наши типовые таблицы ( вывод показывается в Рисунке 8.4 ):
SELECT onum, cname, Orders.cnum, Orders.snum
FROM Salespeople, Customers,Orders
WHERE Customers.city < > Salespeople.city
AND Orders.cnum = Customers.cnum
AND Orders.snum = Salespeople.snum;
=============== SQL Execution Log ==============
| |
| SELECT onum, cname, Orders.cnum, Orders.snum |
| FROM Salespeople, Customers, Orders |
| WHERE Customers.city < > Salespeople.city |
| AND Orders.cnum = Customers.cnum |
| AND Orders.snum = Salespeople.snum; |
| =============================================== |
| onum cname cnum snum |
| ------ ------- ----- ----- |
| 3001 Cisneros 2008 1007 |
| 3002 Pereira 2007 1004 |
| 3006 Cisneros 2008 1007 |
| 3009 Giovanni 2002 1003 |
| 3007 Grass 2004 1002 |
| 3010 Grass 2004 1002 |
===============================================
Рисунок 8. 4: Объединение трех таблиц
Хотя эта команда выглядит скорее как комплексная, вы можете следо-
вать за логикой, просто проверяя - что заказчики не размещены в тех
городах где размещены их продавцы ( совпадение двух snum полей ), и
что перечисленные порядки - выполнены с помощью этих заказчиков( сов-
падение порядков с полями cnum и snum в таблице Порядков ).
Теперь вы больше не ограничиваетесь просмотром одной таблицы в каж-
дый момент времени. Кроме того, вы можете делать сложные сравнения
между любыми полями любого числа таблиц и использовать полученные ре-
зультаты чтобы решать какую информацию вы бы хотели видеть. Фактичес-
ки, эта методика настолько полезна для построения связей, что она час-
то используется для создания их внутри одиночной таблицы. Это будет
правильным: вы сможете объединить таблицу с собой, а это очень удобная
вещь.
Это будет темой Главы 9.
1. Напишите запрос который бы вывел список номеров порядков сопровож-
дающихся именем заказчика который создавал эти порядки.
2. Напишите запрос который бы выдавал имена продавца и заказчика для
каждого порядка после номера порядков.
3. Напишите запрос который бы выводил всех заказчиков обслуживаемых
продавцом с комиссионными выше 12% . Выведите имя заказчика, имя
продавца, и ставку комиссионных продавца.
4. Напишите запрос который вычислил бы сумму комиссионных продавца для
каждого порядка заказчика с оценкой выше 100.
|
|
|
|