Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
all_lab.doc
Скачиваний:
56
Добавлен:
14.11.2019
Размер:
1.42 Mб
Скачать

Задание 2

  1. Вывести идентификаторы, даты рождения и адреса e-mail сотрудников, родившихся в апреле.

  2. Вывести идентификаторы, даты рождения и имена супругов сотрудников, родившихся в 1968 г., и отсортируйте записи на основе имен их супругов.

  3. Выведите идентификаторы сотрудников, родившихся в текущем месяце.

  4. Сколько в базе данных имеется уникальных годов рождения?

  5. Вывести список уникальных годов рождения и число сотрудников, родившихся в каждом таком году.

  6. Сколько сотрудников родились в каждом месяце? Выдача должна содержать названия месяцев (не номера), и записи должны быть упорядочены по убыванию по месяцам, начиная от наибольшего номера.

Задание 3

  1. Найти и вывести идентификаторы и имена супругов всех сотрудников, которые состоят в браке.

  2. Изменить предыдущее задание так, чтобы вывод был отсортирован по именам супругов.

  3. Сколько имеется сотрудников каждого пола (мужчин и женщин)?

  4. Сколько сотрудников состоят в браке, и сколько холостых?

  5. Найдите общее число детей.

  6. Сделайте уникальные группы по количеству детей и определите число детей каждой группы. Отсортируйте вывод групп по убыванию по количеству детей.

6. Переменные и временные таблицы. Многотабличные запросы

Часто результаты запроса необходимо использовать в последующих запросах. Для этого полученные данные необходимо сохранить во временных структурах. Эту задачу решают переменные SQL и временные таблицы.

Переменные SQL

СУБД MySQL предоставляет возможность сохранения результатов текущего запроса для использования в следующих запросах в переменных SQL. Объявление переменных начинается с символа @, за которым следует имя переменной. Значения переменным присваиваются посредством оператора SELECT с использованием символа присваивания «:=».

Рассмотрим учебную базу данных, созданную для компьютерного магазина, торгующего комплектующими (скрипт test.sql).

База данных состоит из четырех таблиц:

Catalogs – список торговых групп; Products – товарные позиции; Users – список зарегистрированных пользователей; Orders – список осуществленных сделок.

Таблица сatalogs предназначена для хранения торговых групп, таких как «Материнские платы», «Процессоры», «Видеокарты» и т.п. Таблица состоит из двух полей:

id_catalog – уникальный номер;

name – имя раздела.

Таблица products содержит конкретные товарные позиции, такие как «Celeron 2.0GHz», «Intel Pentium 4 3.0GHz» и т.п. Таблица состоит из семи полей:

id_product – уникальный номер товарной позиции;

name – название товарной позиции;

price – цена;

count – количество товарных позиций на складе;

mark – относительная оценка товара;

description – описание;

id_catalog – номер торговой группы из таблицы catalogs, которой принадлежит товарная позиция.

Замечание: Обратите внимание, что в таблице products содержится поле id_catalogs, которое поддерживает связь с таблицей catalogs. Такие поля в теории баз данных называются внешними ключами.

Таблица users содержит записи с информацией о зарегестрирвоанных покупателях и состоит из восьми полей:

id_user – уникальный номер покупателя;

surname – фамилия покупателя;

patronymic – отчество покупателя;

name – имя покупателя;

phone – телефон покупателя (если имеется);

email – e-mail покупателя (если имеется);

url – домашняя страница покупателя (если имеется);

status – статус покупателя, поле типа ENUM, которое может принимать одно из четырех значений: авторизованный покупатель (active), неавторизованный покупатель (passive), заблокированный покупатель (lock) и активный покупатель (gold).

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

id_order – уникальный номер сделки;

id_user – номер пользователя из таблицы users;

ordertime – время совершения сделки;

number – число приобретенных товаров;

id_product – номер товарной позиции из таблицы products.

Замечание: Обратите внимание, что все таблицы содержат уникальный идентификатор, который является первичным ключом таблицы.

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

Пример. Объявление и использование переменных SQL

SELECT @total := COUNT(*) FROM `products`

@total := COUNT(*)

30

SELECT @total

@total

30

В примере объявляется переменная @total, которой присваивается число записей в таблице products учебной базы test. Затем в рамках текущего сеанса в последующих запросах появляется возможность использования этой переменной.

Замечание: Переменная действует только в рамках одного сеанса соединения с сервером MySQL и прекращает свое существование после разрыва соединения.

Переменные также могут объявляться при помощи оператора SET, например:

SET @last = CURDATE() - INTERVAL 7 DAY;

Просмотр SELECT CURDATE(), @last;

CURDATE()

@last

15.03.2007

2007-03-08

Удобство использования оператора SET заключаетмся в том, что он, в отличие от оператора SELECT, не возвращает результирующую таблицу.

Временные таблицы

Переменная SQL позволяет сохранить одно промежуточное знаечние. Когда необходимо сохранить результирующую таблицу, прибегают к временным таблицам.

Создание временных таблиц осуществляется при помощи оператора CREATE TEMPORARY TABLE, синтаксис которого ничем не отличается от синтаксиса оператора CREATE TABLE.

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

Содание временной таблицы temp:

CREATE TEMPORARY TABLE temp (id_catalog INT, name VARCHAR(50));

Просмотр структуры таблицы:

DESCRIBE temp;

Если возникает необходимость удалить таблицу до момента завершения соединения с сервером, можно воспользоваться оператором DROP TABLE.

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

Содание временной таблицы temp при помощи вложенного запроса:

CREATE TEMPORARY TABLE temp

SELECT id_catalog, COUNT(id_catalog) AS total

FROM products GROUP BY id_catalog;

Просмотр результата SELECT * FROM temp.

id_catalog

total

  1

  9

  2

  6

  3

  4

  4

  5

  5

  6

Следует обратить внимание на тот факт, что при таком способе создания таблицы не требуется определять структуру таблицы temp – она автоматически принимает структуру результирующей таблицы оператора SELECT.

Временная таблица temp может выступать в качестве предмета запроса. Например, подсчитаем сумму значений столбца total.

SELECT SUM(total) FROM temp

SUM(total)

30

Замечание: В MySQL 5.0.1 появилась серьезная альтернатива временным таблицам в виде представлений (Views). На самом деле представления часто также являются временными таблицами, только об их создании и уничтожении заботится СУБД MySQL.

Перекрестное соединение таблиц

Рассмотренные ранее SQL-запросы обращались к одной таблице. Но в реальных приложениях часто требуется использовать сразу несколько таблиц базы данных. Запросы, которые обращаются одновременно к нескольким таблицам, называются многотабличными запросами. Именно в таких запросах проявляется одно из преимуществ реляционных баз данных – связь таблиц друг с другом.

Рассмотрим несколько сложных запросов на примере учебной базы данных test.

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

SELECT `products`.`name` , `products`.`price`

FROM `products`, `catalogs`

WHERE `products`.`id_catalog`=`catalogs`.`id_catalog` AND

`catalogs`.`name` = 'Жёсткие диски';

name

price

Maxtor 6Y120P0

  2 456

Maxtor 6B200P0

  3 589

Samsung SP0812C

  2 093

Seagate Barracuda ST3160023A

  3 139

Seagate ST3120026A

  2 468

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

SELECT `catalogs`.`name`, count(id_product), sum(count)

FROM `products`, `catalogs`

WHERE `products`.`id_catalog`=`catalogs`.`id_catalog`

group by `products`.`id_catalog`

name

count(id_product)

sum(count)

Процессоры

  9

47

Материнские платы

  6

27

Видеоадаптеры

  4

17

Жёсткие диски

  5

26

Оперативная память

  6

85

Обратите внимание, что обязательным условием в данных запросах является равенство полей id_catalogs таблиц products и catalogs (`products`.`id_catalog`=`catalogs`.`id_catalog`). Именно при помощи данного условия осуществляется связь этих двух таблиц.

Среди таблиц учебной базы данных test примечательной является таблица orders, которая содержит внешний ключ id_product для связи с таблицей products и внешний ключ id_user для связи с таблицей users. Поэтому, чтобы результирующая таблица содержала данные заказа, фамилию покупателя и название товара, требуется осуществить трехтабличный запрос.

SELECT `orders`.`id_order`, `users`.`surname`, `orders`.`ordertime`, `products`.`name`

FROM `products`, `users`, `orders`

WHERE `products`.`id_product` = `orders`.`id_product` AND

`users`.`id_user` = `orders`.`id_user`

id_order

surname

ordertime

name

  1

Симдянов

04.01.2005 10:39

Intel Pentium 4 3.0GHz

  2

Корнеев

10.02.2005 9:40

Gigabyte GA-8I848P-RS

  3

Иванов

18.02.2005 13:41

Maxtor 6Y120P0

  4

Симдянов

10.03.2005 18:20

Maxtor 6Y120P0

  5

Симдянов

17.03.2005 19:15

Maxtor 6Y120P0

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

SELECT `orders`.`id_order`, `users`.`surname`, `orders`.`ordertime`, `products`.`name`, `catalogs`.`name`

FROM `products`, `users`, `orders`, `catalogs`

WHERE `products`.`id_product` = `orders`.`id_product` AND

`users`.`id_user` = `orders`.`id_user` AND

`catalogs`.`id_catalog` = `products`.`id_catalog`

id_order

surname

ordertime

name

name_1

  1

Симдянов

04.01.2005 10:39

Intel Pentium 4 3.0GHz

Процессоры

  2

Корнеев

10.02.2005 9:40

Gigabyte GA-8I848P-RS

Материнские платы

  3

Иванов

18.02.2005 13:41

Maxtor 6Y120P0

Жёсткие диски

  4

Симдянов

10.03.2005 18:20

Maxtor 6Y120P0

Жёсткие диски

  5

Симдянов

17.03.2005 19:15

Maxtor 6Y120P0

Жёсткие диски

С увеличением количества таблиц в запросе резко возрастает объем работы, необходимой для выполнения запроса, поэтому по возможности в запросе не следует использовать больше трех-четырех таблиц.

Объединение таблиц при помощи JOIN

Оператор JOIN позволяет объединять таблицы и имеет многочисленные варианты использования, которые будут рассмотрены далее. В SQL-запросе данный оператор располагается между именами соединяемых таблиц после ключевого слова FROM. Без дополнительных ключевых слов соединение при помощи ключевого слова JOIN аналогично перекрестному соединению таблиц.

Например,

SELECT *

FROM `products`, `catalogs`

WHERE `products`.`id_catalog` = `catalogs`.`id_catalog`

SELECT *

FROM `products` JOIN `catalogs`

WHERE `products`.`id_catalog` = `catalogs`.`id_catalog`

Эти два запроса полностью идентичны. Для формирвоания условия а запросах, использующих объединение JOIN, вместо ключевого слова WHERE предпочтительно использовать ключевое слово ON, как это продемонстрирвоано ниже:

SELECT *

FROM `products` JOIN `catalogs`

ON `products`.`id_catalog` = `catalogs`.`id_catalog`

Замечание: Ключевое слово JOIN имеет два синонима: CROSS JOIN и INNER JOIN.

Помимо перекрестного соединения таблиц, предусмотрено левое и правое соединение таблиц, которое осуществляется при помощи конструкций LEFT JOIN и RIGHT JOIN соответственно.

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

Ключевое слово USING()

Другим способом установки связи между таблицами при правом и левом соединениях является использование ключевого слова USING(). В круглых скобках перечисляются имена столбцов, которые должны присутствовать в обеих таблицах и для которых необходимо соблюдение равенства. Данный оператор предназначен для создания более компактных SQL-запросов.

Например, при помощи JOIN … USING() извлечем число товарных позиций в каталоге.

SELECT `catalogs`.`name`, COUNT(id_product)

FROM `catalogs` JOIN `products` USING(id_catalog)

GROUP by `products`.`id_catalog`;

name

count(id_product)

Процессоры

  9

Материнские платы

  6

Видеоадаптеры

  4

Жёсткие диски

  5

Оперативная память

  6

Предположим, что происходит расширение ассортимента товарных позиций и в списке каталогов появляется новый каталог ‘Периферия’. SQL-запрос, добавляющий этот каталог:

INSERT INTO catalogs VALUES (null, 'Периферия');

Однако предыдущий запрос не отразит наличие нового каталога в электронном магазине, т.к. таблица products еще не содержит ни одной записи, относящейся к новому каталогу. Для того, чтобы название каталога ‘Периферия’ появилось в результирующей таблице, необходимо провести левое соединение таблиц catalogs и products, причем таблица catalogs должна выступать в качестве «левой» таблицы.

SELECT `catalogs`.`name`, COUNT(id_product)

FROM `catalogs` LEFT JOIN `products` USING(id_catalog)

GROUP by `products`.`id_catalog`;

name

count(id_product)

Периферия

0

Процессоры

  9

Материнские платы

  6

Видеоадаптеры

  4

Жёсткие диски

  5

Оперативная память

  6

Пусть требуется вывести список покупателей и число осуществленных ими покупок, причем покупателей необходимо отсортировать в порядке убывания числа оплаченных ими заказов.

SELECT `users`.`surname`, `users`.`name`, `users`.`patronymic`, COUNT(`orders`.`id_order`) AS total

FROM `users` JOIN `orders` USING(id_user)

GROUP BY users.`id_user`

ORDER BY total DESC

surname

name

patronymic

total

Симдянов

Игорь

Вячеславович

  3

Иванов

Александр

Валерьевич

  1

Корнеев

Александр

Александрович

  1

Можно заметить, что в списке присутствуют только те покупатели, которые оплатили хотя бы одну покупку, покупатели, на счету у которых нет ни одной покупки, в список не входят. Для того, чтобы вывести полный список покупателей, необходимо вместо перескрестного соединения таблиц users и orders воспользоваться левым соединением, где в качестве «левой» таблицы выступит таблица users:

SELECT `users`.`surname`, `users`.`name`, `users`.`patronymic`, COUNT(`orders`.`id_order`) AS total

FROM `users` LEFT JOIN `orders` USING(id_user)

GROUP BY users.`id_user`

ORDER BY total DESC

surname

name

patronymic

total

Симдянов

Игорь

Вячеславович

  3

Иванов

Александр

Валерьевич

  1

Корнеев

Александр

Александрович

  1

Лосев

Сергей

Иванович

0

Кузнецов

Максим

Валерьевич

0

Нехорошев

Анатолий

Юрьевич

0

Ключевое слово WHERE

Помимо условия USING, в запросах на соединение могут использоваться традиционные конструкции условия.

Например, составим запрос, который извлекает список покупателей и число их покупок при условии, что покупателя зовут «Александр».

SELECT `users`.`surname`, `users`.`name`, `users`.`patronymic`, COUNT(`orders`.`id_order`) AS total

FROM `users` LEFT JOIN `orders` USING(id_user)

WHERE name = 'Александр'

GROUP BY users.`id_user`

ORDER BY total DESC

surname

name

patronymic

total

Иванов

Александр

Валерьевич

  1

Корнеев

Александр

Александрович

  1

Для этого используется условие WHERE name = 'Александр'. Однако использовать столбец total в условии WHERE уже не получится, т.к. групповой столбец, сформированный агрегатной функцией COUNT() и конструкцией GROUP BY.

Для формирования условия с его участием необходимо использовать условие HAVING.

Пусть требуется извлечь всех покупателей магазина, число покупок (total) у которых меньше трёх:

SELECT `users`.`surname`, `users`.`name`, `users`.`patronymic`, COUNT(`orders`.`id_order`) AS total

FROM `users` LEFT JOIN `orders` USING(id_user)

GROUP BY users.`id_user`

HAVING total < 3

ORDER BY total DESC

surname

name

patronymic

total

Иванов

Александр

Валерьевич

  1

Корнеев

Александр

Александрович

  1

Лосев

Сергей

Иванович

0

Кузнецов

Максим

Валерьевич

0

Нехорошев

Анатолий

Юрьевич

0

Задания

Замечание: При создании таблиц необходимо выбрать тип таблицы – InnoDB, так как это единственный тип который поддерживает внешние ключи и каскадное удаление.

Вариант 1

Создать БД, состоящую из таблиц АВТОР (Фамилия, имя, отчество, пол, дата рождения, телефон) и КНИГА (Название, цена, тематика, издательство, тираж). Дополнить первичными и внешними ключами, уточнить структуру и связать таблицы в предположении, что у книги может быть только один автор. Построить диаграмму и сохранить ее.

Заполнить таблицы данными – 5-6 записей.

Реализовать следующие запросы:

  1. Вывести список авторов, работающих в издательстве «Мир».

  2. Предположим, что не все зарегестрированные в БД авторы имеют изданные книги. Вывести список всех авторов с указанием тематики изданных книг.

  3. Найти авторов, работающих как с издательством «Мир», так и с издательством «АСТ».

  4. Рассчитать общую стоимость тиража и 5% налог с продаж для книг каждого автора.

  5. На какую сумму были проданы книги каждого автора?

  6. Определить число различных наименований проданных в издательстве «АСТ» книг, количество книг каждого наименования и вырученную сумму.

Вариант 2

Создать БД, состоящую из таблиц РЕЙС (№ рейса, конечный пункт, дата вылета, продолжительность маршрута) и БИЛЕТ (Номер места, дата продажи, фамилия пассажира). Дополнить первичными и внешними ключами, уточнить структуру и связать таблицы. Построить диаграмму и сохранить ее.

Заполнить таблицы данными – 5-6 записей.

Реализовать следующие запросы:

  1. Вывести номера мест и дату продажи билетов на рейсы до Москвы.

  2. Вывести список рейсов, на которые не были проданы билеты.

  3. Составить список пассажиров, которые летают и в Москву, и в Киев.

  4. Рассчитать общую стоимость билетов для каждого рейса, 5% налог с продаж и общий доход рейса.

  5. Определить количество проданных на каждый рейс билетов.

  6. На какую сумму были проданы билеты в день вылета?

Вариант 3

Создать БД, состоящую из таблиц БЛЮДО (Название, время приготовления, повар, стоимость_блюда) и КОМПОНЕНТ (Название, калорийность, вес, стоимость 100 гр). Дополнить первичными и внешними ключами, уточнить структуру и связать таблицы в предположении, что один определенный компонент принимает участие только в одном блюде. Построить диаграмму и сохранить ее.

Заполнить таблицы данными – 5-6 записей.

Реализовать следующие запросы:

  1. Вывести список компонент, которые использует повар Иванов для приготовления своих блюд.

  2. Вывести список поваров, использующих для приготовления блюд и масло и молоко.

  3. Сформировать список поваров, которые используют масло, но обходятся без молока.

  4. Рассчитать общую стоимость блюда по компонентам и его калорийность.

  5. Для каждого повара определить количество используемых компонентов.

  6. Для каждого повара определить колчество десертов и количество компонентов в каждом из них.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]