- •Примеры запросов.
- •Вычисления в агрегатных функциях.
- •Найти сделку с максимальной стоимостью для каждого торгового агента. Можно сделать персональный запрос для каждого из них, выбрав max(amt) из таблицы «Сделки». Можно записать следующий запрос:
- •Узнать, какие торговые агенты имеют заработок от одной сделки более чем 3000, и в какой день. Для этого необходимо ввести следующий запрос:
Найти сделку с максимальной стоимостью для каждого торгового агента. Можно сделать персональный запрос для каждого из них, выбрав max(amt) из таблицы «Сделки». Можно записать следующий запрос:
SELECT snum, MAX (amt) FROM Orders GROUP BY snum;
Результат выполнения запроса:
SNUM |
|
1001 |
767.19 |
1002 |
1713.23 |
1003 |
75.75 |
1014 |
1309.95 |
1007 |
1098.16 |
В данном случае таблица группируется относительно номера торгового агента, поэтому поле SNUM присутствует в списке вывода запроса и в предложении GROUP BY.
Использование HAVING. HAVING подобен WHERE – он задает условия отбора групп так же, как это делает WHERE для строк.
Узнать, какие торговые агенты имеют заработок от одной сделки более чем 3000, и в какой день. Для этого необходимо ввести следующий запрос:
SELECT snum, odate, MAX ((amt))
FROM Orders
GROUP BY snum, odate
HAVING MAX ((amt)) > 3000.00;
Результат работы запроса:
SNUM |
ODATE |
------ |
1001 |
10/05/2011 |
4723.00 |
1001 |
10/06/2011 |
9891.88 |
1002 |
10/03/2011 |
5160.45 |
Обратите внимание! В предложении HAVING нельзя проверять имена полей на какое-либо условие – для этого существует WHERE. То, что проверяется в предложении HAVING должно иметь только одно значение для группы.
2. Использование условий выборки и агрегатных функций SQL в клиентском приложении. Для того чтобы проиллюстрировать работу оператора SELECT, модифицируем структуру таблицы PhoneLib. Добавим дополнительные поля: номер телефона (PhoneNum) и тип телефона (PhoneType) и модифицируем данные таблицы. Эту операцию можно выполнить посредством оболочки phpMyAdmin (рис. 3.1) или с помощью операторов SQL:
ALTER TABLE PhoneLib
ADD PhoneNum VARCHAR(12) CHARACTER SET cp1251
COLLATE cp1251_bin NOT NULL AFTER BDate
ALTER TABLE PhoneLib
ADD PHONETYPE VARCHAR(15) CHARACTER SET WIN1251
COLLATE cp1251_bin AFTER PhoneNum
Рисунок 3.1 – Добавление нового поля в таблицу PhoneLib
посредством phpMyAdmin
В результате ввода данных получаем таблицу, представленную на рис. 3.2.
Рисунок 3.2 – Модифицированная таблица «Телефонный справочник»
Необходимо отметить, что полученное отношение не является нормализованным и, как следствие, имеют место аномалии добавления, удаления и обновления. Это значит, что:
– если необходимо добавить рабочий телефон Диброва Виталия Семеновича, придется дублировать содержимое полей Ф.И.О. и дата рождения;
– в базе данных не может содержаться информация о человеке, у которого нет телефона;
– при изменении паспортных данных человека необходимо будет поменять информацию в нескольких строках таблицы.
Для исключения указанных аномалий выполняется операция декомпозиции отношения, которая будет рассмотрена в ЛР №4.
Модифицируем клиентское приложение, разработанное в ЛР №2. Выведем информацию, содержащуюся в добавленных полях «Номер телефона» (PhoneNum)и «Тип номера телефона»(PhoneType)так, как показано на рис. 3.3.
Рисунок 3.3 – Измененная структура таблицы PhoneLib с введенными данными
Заметим, что содержимое таблицы выводится в том порядке, в каком записи об абонентах поступали в базу данных, что затрудняет поиск информации.
Разработаем интерфейс для исследования работы оператора SELECT. Для сортировки записей таблицы по содержимому поля «Ф.И.О.» добавим в файл «phplib.php» две кнопки «Показать», по нажатию которой выполняется SQL запрос сортировки абонентов алфавитному порядку, и «Список абонентов», возвращающий список абонентов в исходное состояние (см. рис 3.4).
Рисунок 3.4 – Форма сортировки абонентов
SQL-запрос, выполняющий сортировку имеет вид:
SELECT * FROM PhoneLib ORDER BY FIO
Поиск информации в таблице станет удобней, если в ней будут выведены не все записи, а только те, которые удовлетворяют условию поиска (например, заданному типу телефона). Добавим в форму текстовое поле:
<input name="phone_type" type="text" size="12">
для ввода пользователем типа телефона для отображения абонентов, удовлетворяющих условию поиска, и кнопку «Показать»:
<input name="select_phone_type" type="submit" value="Показать">
по нажатию которой выполняется соответствующий SQL-запрос:
SELECT * FROM $userstable WHERE PhoneType='Рабочий'
Результат работы модифицированного приложения показан на рис. 3.5.
Рисунок 3.5 – Работа приложения с фильтром записей
Реализуем запросы типа «Вывести количество номеров каждого абонента» (результат работы представлен на рис. 3.6):
SELECT FIO, Count(*) FROM PhoneLib
GROUP BY FIO ORDER BY FIO
и «Вывести имена и количество телефонов абонентов, имеющих 2 и более номеров» (результат работы представлен на рис. 3.7):
SELECT FIO, Count(*) FROM PhoneLib
GROUP BY FIO
HAVING (Count(*)>=2) ORDER BY FIO
Рисунок 3.6 – Реализация запроса «Вывести количество
номеров каждого абонента»
Рисунок 3.6 – Реализация запроса «Вывести имена и количество телефонов абонентов, имеющих 2 и более номеров»
Самостоятельно: Реализуйте запрос и форму вывода
«Вывести всех абонентов телефонной книги без повторения имен».