Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
экзамен БД.docx
Скачиваний:
7
Добавлен:
20.04.2019
Размер:
240.87 Кб
Скачать

Использование параметров group by и having

В предыдущих примерах в качестве группы рассматривался весь набор записей, полученный в результате выполнения запроса. При помощи параметра GROUP BY оператора SELECT можно указать способ разбиения полученного в результате выполнения запроса набора записей на группы. В параметре GROUP BY задается столбец (или столбцы), по значениям которого будет производиться группировка. При выполнении оператора SELECT, в котором присутствует параметр GROUP BY, СУБД проанализирует значение указанного столбца во всех строках, отобранных в результате выполнения запроса. Все строки, где значение указанного в параметре GROUP BY столбца одно и тоже, попадут в одну группу. После этого для каждой из групп будет вычислена указанная в параметре SELECT групповая функция. Например:

-- вывод имен менеджеров и количества продаж каждого

-- из менеджеров

SELECT Name, COUNT(*) “Количество продаж”

FROM Managers m, Outgoing o

WHERE m.Man_id=o.Man_id

GROUP BY Name;

В данном запросе СУБД сначала выделит группы записей, относящиеся к разным менеджерам (в зависимости от значения столбца Name) и для каждой получившейся группы посчитает количество записей.

Параметр HAVING оператора SELECT используется для исключения групп из результирующего набора записей на основе результатов выполнения групповых функций. После параметра HAVING также как и после параметра WHERE указывается условие фильтрации, но в отличие от параметра WHERE, условия которого используются для фильтрации отдельных строк, условия, указанные в параметре HAVING используются для фильтрации целых групп. Например:

-- отбор менеджеров, осуществивших за последнюю неделю

-- не менее 10 сделок продажи

SELECT Name, COUNT(*) “Количество продаж”

FROM Managers m, Outgoing o

WHERE m.Man_id=o.Man_id AND o.Out_Date >= TRUNC(SYSDATE)-7

GROUP BY Name

HAVING COUNT(*) >= 10;

Запросы с использованием нескольких таблиц Запросы с использованием соединений

Декартово произведение таблиц

Соединения – это подмножества декартова произведения. Так как декартово произведение N таблиц – это таблица, содержащая все возможные строки R, такие, что R является сцеплением какой-либо строки из первой таблицы, строки из второй таблицы, ... и строки из N-й таблицы, то осталось лишь выяснить, можно ли с помощью SELECT получить декартово произведение. Для получения декартова произведения нескольких таблиц надо указать в параметре FROM перечень перемножаемых таблиц, а во фразе SELECT – все их столбцы.

Так, для получения декартова произведения таблиц Managers и Contracts, необходимо выполнить запрос:

SELECT Managers.*, Contracts.*

FROM Managers, Contracts;

В зависимости от количества строк, содержащихся в обеих таблицах, результирующий набор записей будет содержать количество строк, равно N*M, где N – количество строк в таблице Managers, а M – количество строк в таблице Contracts. При выполнении декартово произведения над большим количеством таблиц, количество получившихся строк еще более возрастет. Если взять любой из результатов, полученных после выполнения декартово произведения, то станет понятно, что актуальными записями являются лишь очень немногие. Поэтому операция декартово произведения является лишь промежуточным этапом.

Эквисоединение таблиц

Актуальные строки можно отобрать из декартово произведения путем ввода в запрос параметра WHERE, в котором устанавливается соответствие между полями, посредством которых каждая пара таблиц связана между собой.

Эквисоединение таблиц в предыдущем запросе выглядит следующим образом:

SELECT Managers.*, Contracts.*

FROM Managers, Contracts

WHERE Managers.Man_id = Contracts.Man_id;

Естественное соединение таблиц

Естественным соединением таблиц называется такое соединение, из которого исключены дубликаты столбцов, по которым проводилось эквисоединение (Managers.Man_id и Contracts.Man_id). Для исключения дубликатов в операторе SELECT необходимо явно указать только один из столбцов этих пар, принадлежащего главной таблице:

SELECT Managers.Man_id, D_id, Name, Hire_Date, Procent,

Comments, Parent_id, DayFrom, DayTo

FROM Managers, Contracts

WHERE Managers.Man_id = Contracts.Man_id;

Композиция таблиц

Композицией таблиц называется соединение, из которого полностью исключены столбцы, по которым производилось соединение:

SELECT D_id, Name, Hire_Date, Procent,

Comments, Parent_id, DayFrom, DayTo

FROM Managers, Contracts

WHERE Managers.Man_id = Contracts.Man_id;

Соединение таблиц с дополнительным условием

Наравне с уловными выражениями, предназначенными для указания способа соединения таблиц между собой, в параметре WHERE можно дополнительно указывать все описанные выше дополнительные условия фильтрации, объединенные с условными выражениями соединения при помощи оператора AND. Например:

-- получение информации о менеджерах и заключенных

-- ими контрактах за последнюю неделю

SELECT Name, DayFrom, DayTo

FROM Managers, Contracts

WHERE Managers.Man_id = Contracts.Man_id

AND DayFrom BETWEEN TRUNC(SYSDATE)-7 AND SYSDATE;

Соединение таблицы со своей копией

В ряде приложений возникает необходимость одновременной обработки данных какой-либо таблицы и одной или нескольких ее копий, создаваемых на время выполнения запроса.

Например, при выводе информации о менеджерах интересно было бы вместо номера начальника получить его полное имя. Кроме того, данная возможность часто используется для выявления объектов, имеющие общие значения атрибутов и находящиеся в одной таблице. В последнем случае в параметре WHERE устанавливают равенство значений всех одноименных столбцов этих таблиц, по значениям которых необходимо выявить совпадения, а для остальных установить неравенство значений (обычно достаточно установить неравенство значений полей, входящих в состав первичного ключа).

Временную копию таблицы можно сформировать, указав имя псевдонима за именем таблицы во фразе FROM. Так, с помощью фразы

FROM Managers M1, Managers M2

будут сформированы две копии таблицы MANAGERS с именами M1 и M2.

Примеры соединения таблиц со своей копией:

-- получение имен менеджеров и имен их начальников

SELECT M1.Name, M2.Name

FROM Managers M1, Managers M2

WHERE M1.Parent_id=M2.Man_id;

 

-- получение списка однофамильцев

SELECT M1.*

FROM Managers M1, Managers M2

WHERE M1.Name=M2.Name AND M1.Man_id<>M2.Man_id;

 

Внутреннее и внешнее объединение таблиц

Ранее были рассмотрены способы получения связанных между собой данных, находящихся в нескольких таблицах, при помощи комбинирования операций декартово произведения и горизонтальной фильтрации строк получившегося набора данных.

Кроме этого во многих СУБД существуют реализации операции внутреннего и внешнего условных соединений таблиц внутри одного запроса – INNER JOIN (внутреннее объединение), LEFT JOIN (полное левое объединение) и RIGHT JOIN (полное правое объединение).

Синтаксис применения операция объединения выглядит следующим образом:

 

SELECT список_полей

FROM таблица1 ( INNER | LEFT | RIGHT ) JOIN таблица2

ON таблица1.связующее_поле = таблица2.связующее_поле;

 

В результате выполнения внутреннего объединения из кортежей двух объединяемых таблиц остаются только те, для которых выполняется указанное условие. Например:

 

-- получение имен менеджеров и связанных с ними дилеров

-- (менеджеры, не связанные с дилерами и дилеры не связанные

-- с менеджерами исключатся из результата)

SELECT Managers.Name, Dealers.Name

FROM Managers INNER JOIN Dealers

ON Managers.D_id=Dealers.D_id;

 

При полном (внешнем) левом объединении из кортежей двух объединяемых таблиц остаются все кортежи таблицы, указанной слева от условного выражения, и кортежи правой таблицы, для которых выполняется указанное условие. Например:

 

-- получение всех менеджеров и связанных с ними дилеров,

-- включая менеджеров, не связанных с дилерами

SELECT Managers.Name, Dealers.Name

FROM Managers LEFT JOIN Dealers

ON Managers.D_id=Dealers.D_id;

 

При полном (внешнем) правом объединении из кортежей двух объединяемых таблиц остаются все кортежи таблицы, указанной справа от условного выражения, и кортежи левой таблицы, для которых выполняется указанное условие. Например:

 

-- получение всех дилеров и связанных с ними менеджеров,

-- включая дилеров, не связанных с менеджерами

SELECT Managers.Name, Dealers.Name

FROM Managers RIGHT JOIN Dealers

ON Managers.D_id=Dealers.D_id;

 

В СУБД ORACLE также для реализации левого внешнего объединения используется оператор (+) в предложении WHERE, который ставиться справа от столбца, по которому осуществляется соединение, справа от знака =. Аналогично для правого объединения оператор (+) ставиться справа от столбца слева от знака равенства. Например:

 

-- получение всех менеджеров и связанных с ними дилеров,

-- включая менеджеров, не связанных с дилерами

SELECT Managers.Name, Dealers.Name

FROM Managers, Dealers

WHERE Managers.D_id=Dealers.D_id(+);

 

-- получение всех дилеров и связанных с ними менеджеров,

-- включая дилеров, не связанных с менеджерами

SELECT Managers.Name, Dealers.Name

FROM Managers, Dealers

WHERE Managers.D_id(+)=Dealers.D_id;