
- •2.Этапы развития субд.
- •Архитектура базы данных. Физическая и логическая независимость
- •18.Структура оператора select.
- •20.Предложение where и условия поиска
- •14.Создание таблицы базы данных
- •12.Типы данных
- •11.Специальные операции реляционной алгебры.
- •10.Теоретико-множественные операции над отношениям
- •8.Реляционная модель. Понятие отношения.
- •15. Язык манипуляции данными (ямд)
- •16.Ограничения, налагаемые на столбцы.
- •17.Ссылочная целостность.
- •21.Квалификатор distinct. Предложение order by.
- •22.Использование агрегатных функций. Предложение group by.
- •24.Виды соединений
- •26.Внутреннее и внешнее соединения join.
- •27.Вложенные запросы. Основные правила при задании подзапросов.
- •30. Представления в базах данных
- •32.Этапы проектирования бд.
- •33.Нормализация отношений (функциональная и транзитивная зависимости).
- •35.Понятие и свойства транзакции.
- •36.Команды commit и rollback.
- •37.Распределенная обработка данных. Распределенные базы данных
- •38. Модель «клиент-сервер»,- основные функции.
- •39.Модель файлового сервера.
- •40.Модель удалённого доступа к данным.
- •41.Модель сервера баз данных.
- •42.Модель сервера приложений.
18.Структура оператора select.
Оператор SELECT
Оператор SELECT применяется
для извлечения строк, выбранных из одной
или нескольких таблиц. То есть с его
помощью мы задаем столбцы или выражения,
которые надо извлечь (select_выражения),
таблицы (table_references), из которых должна
производиться выборка, и, возможно,
условие (where_definition), которому должны
соответствовать данные в этих столбцах,
и порядок, в котором эти данные нужно
выдать.
Кроме того, оператор SELECT можно использовать для извлечения строк, вычисленных без ссылки на какую-либо таблицу. Например, чтобы вычислить, чему равно 2*2, нужно просто написать
mysql> SELECT 2*2;
Упрощенно структуру оператора SELECT можно представить следующим образом:
SELECT select_выражение1, select_выражение2, ... [FROM table_references [WHERE where_definition] [ORDER BY {число | имя_столбца | формула} [ASC | DESC], ...]]
Квадратные скобки [ ] означают, что использование находящегося в них оператора необязательно, вертикальная черта | означает перечисление возможных вариантов. После ключевого слова ORDER BY указывают имя столбца, число (целое беззнаковое) или формулу и способ упорядочения (по возрастанию – ASC, или по убыванию – DESC). По умолчанию используется упорядочение по возрастанию.
Когда в select_выражении мы пишем «*», это значит выбрать все столбцы. Кроме «*» в select_выражения могут использоваться функции типа max, min и avg.
Предложение HAVING
Предложение HAVING применяется, чтобы задать условия поиска для групп или для агрегатной функции. Предложение HAVING чаще всего используется после предложения GROUP BY в случаях, когда условие поискадолжно проверяться уже после группировки результатов. Если условие поиска можно было бы проверить до группировки, то гораздо эффективней было бы поместить его в предложение WHERE, а не пользоваться предложением HAVING (за счет этого уменьшилось бы количество строк, участвующих в группировке). Если предложение GROUP BY отсутствует, то HAVING может применяться только в отношении агрегатной функции в списке выборки. В этом случае предложение HAVING действует точно так же, как предложение WHERE. Если попытаться использовать HAVING как-нибудь по-другому, то SQL Server выдаст сообщение об ошибке.
Предложение HAVING имеет такой синтаксис:
HAVING <условие_поиска>
Здесь условие_поиска имеет такой же смысл, что и условие поиска. (См. раздел "Предложение WHERE и условие поиска" выше в данной лекции). Единственным различием между предложениями HAVING и WHERE является то, что предложение HAVING может содержать агрегатную функцию в условии поиска, а предложение WHERE – нет.
П
римечание. Агрегатные
функции можно применять в
предложениях SELECT и HAVING, но не в
предложенииWHERE.
Ниже приведен пример запроса, использующего предложение HAVING для поиска книг, сгруппированных по типам и по издательствам, средняя цена на которые превышает 15 долларов:
SELECT type, pub_id, AVG(price) AS "Средняя цена"
FROM titles
GROUP BY type, pub_id
HAVING AVG(price) > 15.00
GO
В набор результатов попадут 4 строки:
type pub_id Средняя цена
--------------------------------------------------
psychology 0877 21.59
trad_cook 0877 15.96
business 1389 17.31
popular_comp 1389 21.48
В предложениях HAVING можно употреблять логические операции. Ниже показан несколько измененный последний пример, в нем теперь применяется логическая операция AND:
SELECT type, pub_id, AVG(price) AS "Средняя цена"
FROM titles
GROUP BY type, pub_id
HAVING AVG(price) >= 15.00 AND
AVG(price) <= 20.00
GO
В набор результатов попадут 2 строки:
type pub_id Средняя цена
--------------------------------------------------
trad_cook 0877 15.96
business 1389 17.31
Такой же результат получится, если вместо AND применить предложение BETWEEN, вот так:
SELECT type, pub_id, AVG(price) AS "Средняя цена"
FROM titles
GROUP BY type, pub_id
HAVING AVG(price) BETWEEN 15.00 AND 20.00
GO
Чтобы применять HAVING без предложения GROUP BY, нужно иметь агрегатную функцию в списке выборки и в предложении HAVING. Например, чтобы выводить сумму цен на книги типа mod_cook (современная кулинария), только в тех случаях, когда эта сумма будет превышать 20 долларов, можно применять такой запрос:
SELECT SUM(price)
FROM titles
WHERE type = "mod_cook"
HAVING SUM(price) > 20
GO
Если в этом запросе поместить выражение SUM(price) > 20 в предложение WHERE, то SQL Server выдаст сообщение об ошибке, т.к. в предложениях WHEREагрегатные функции применять нельзя.
П римечание. Помните, что предложение HAVING можно применять, только когда вы добавляете условие поиска, проверяющее результаты группировки при помощи предложения GROUP BY или проверяющее результат агрегатной функции. В остальных случаях условия поиска следует задавать в предложениях WHERE.
Предложение ORDER BY
Предложение ORDER BY применяется, чтобы задать порядок, в котором должны сортироваться строки набора результатов. Пользуясь ключевыми словамиASC и DESC, вы можете задать как возрастающий (ascending, от меньших значений к большим), так и убывающий (descending, от больших значений к меньшим) порядок сортировки. Если порядок сортировки не указать, то по умолчанию будет применяться возрастающий порядок сортировки. В предложении ORDER BY можно задать более одной колонки. Результаты будут сортироваться по первой из заданных колонок, но если в первой колонке встретятся строки с одинаковыми значениями, то они будут сортироваться в порядке возрастания значения из второй колонки, и т.д. Как вы увидите из материала данного раздела, такая сортировка особенно полезна при использовании вместе с предложением GROUP BY. Давайте сначала рассмотрим пример, в котором предложение ORDER BY работает с одной колонкой и сортирует список авторов по фамилии , в возрастающем порядке:
SELECT au_lname, au_fname
FROM authors
ORDER BY au_lname ASC
GO
Набор результатов будет отсортирован в алфавитном порядке по фамилиям авторов. Не забудьте, что чувствительность сортировки к регистру букв, заданная вами при инсталляции SQL Server, повлияет на обработку фамилий вроде "del Castillo".
Если вы хотите отсортировать результаты для более чем одной колонки, то просто добавьте в предложение ORDER BY имена колонок, разделяя их запятыми. Ниже приведен пример запроса, выдающего идентификаторы должностей, фамилии и имена сотрудников, сортирующего вывод сначала по идентификатору должности, затем по фамилии, а затем по имени:
SELECT job_id, lname, fname
FROM employee
ORDER BY job_id, lname, fname
GO
Набор результатов (43 строки) будет выглядеть так:
job_id lname fname
-----------------------------------
2 Cramer Philip
3 Devon Ann
4 Chang Francisco
5 Henriot Paul
5 Hernadez Carlos
5 Labrune Janine
5 Lebihan Laurence
5 Muller Rita
5 Ottlieb Sven
5 Pontes Maria
6 Ashworth Victoria
6 Karttunen Matti
6 Roel Diego
6 Roulet Annette
7 Brown Lesley
7 Ibsen Palle
7 Larsson Maria
7 Nagy Helvetius
. . .
. . .
. . .
13 Accorti Paolo
13 O’Rourke Timothy
13 Schmitt Carine
14 Afonso Pedro
14 Josephs Karin
14 Lincoln Elizabeth
Сортировка по именам (не фамилиям) людей в этом запросе не влияет на набор результатов, потому что там нет даже двух людей с одинаковыми фамилиями и идентификаторами должности.
А теперь давайте рассмотрим предложение ORDER BY, работающее совместно с предложением GROUP BY и агрегатной функцией:
SELECT type, pub_id, AVG(price) AS "Средняя цена"
FROM titles
GROUP BY type, pub_id
ORDER BY Средняя цена
GO
Набор результатов (8 строк) будет выглядеть так:
type pub_id Средняя цена
-------------------------------------------------
UNDECIDED 0877 NULL
business 0736 2.99
business 1389 17.31
mod_cook 0877 11.49
popular_comp 1389 21.48
psychology 0736 11.48
psychology 0877 21.59
trad_cook 0877 15.96
Результаты отсортированы в алфавитном порядке (возрастающем) по типу книг. Также обратите внимание, что в этом запросе в предложении GROUP BYдолжны присутствовать и type, и pub_id, потому что они не являются частью агрегатной функции. Если вы не зададите колонку pub_id в предложенииGROUP BY, то SQL Server выдаст сообщение об ошибке (рис. 14.4).
В предложении ORDER BY нельзя применять агрегатные функции и подзапросы. Однако если вы зададите алиас агрегатной функции в предложении SELECT, то его применить можно в предложении ORDER BY, вот так:
SELECT type, pub_id, AVG(price) AS "Средняя цена"
FROM titles
GROUP BY type, pub_id
ORDER BY type
GO
Предложение GROUP BY
Предложение GROUP BY применяется после предложения WHERE и означает, что строки набора результатов должны быть сгруппированы в соответствии с данными в колонке группировки. Если в предложении SELECT используетсяагрегатная функция, то для каждой группы вычисляется и отображается в выводе итоговое агрегатное значение.Агрегатная функция выполняет вычисления и возвращает значение. (Про агрегатные функции см. раздел "Агрегатные функции" далее.)
П римечание. В предложении GROUP BY в качестве колонок группировки должны быть заданы все колонки из списка выборки (кроме колонок, применяемых для агрегатных функций), в противном случае SQL Server выдаст сообщение об ошибке. Если бы это правило не соблюдалось, результаты нельзя было бы выдать в разумном виде, поскольку колонка, заданная в GROUP BY, должна группировать каждую колонку в списке выборки.
Предложение GROUP BY особенно полезно, когда в предложении SELECT имеется агрегатная функция. Давайте рассмотрим пример оператора SELECT, применяющего предложение GROUP BY для получения сведений об общем количестве проданных книг для каждого из названий книг:
SELECT title_id, SUM(qty)
FROM sales
GROUP BY title_id
GO
Будет выдан набор результатов, содержащий 16 строк:
title_id
----------------------
BU1032 15
BU1111 25
BU2075 35
BU7832 15
MC2222 10
MC3021 40
PC1035 30
PC8888 50
PS1372 20
PS2091 108
PS2106 25
PS3333 15
PS7777 25
TC3218 40
TC4203 20
TC7777 20
Этот запрос не содержит предложения WHERE – оно не нужно. Набор результатов состоит из колонки title_id (идентификатор названия книги) и итоговой колонки, не имеющей заголовка. Для каждого отдельного названия книги будет подсчитано общее количество экземпляров этой книги, это число будет показано в итоговой колонке. Например, пусть значение BU1032 колонки title_id встретится в таблице sales (продажи) два раза, первый раз оно будет обозначать продажу 5 экземпляров книги (колонка qty будет иметь значение 5), а во второй раз будет обозначать продажу книг по другому заказу, на этот раз будет продано 10 экземпляров книги. Агрегатная функция SUM произведет суммирование этих двух продаж, отсюда и получится, что общее количество проданных экземпляров равно 15, что и будет показано в итоговой колонке. Если вы хотите, чтобы итоговая колонка имела заголовок, воспользуйтесь ключевым словом AS, вот так:
SELECT title_id, SUM(qty) AS "Колич прод"
FROM sales
GROUP BY title_id
GO
Теперь набор результатов станет показывать заголовок для итоговой колонки (в наборе результатов содержится 16 строк):
itle_id Колич прод
----------------------------
BU1032 15
BU1111 25
BU2075 35
BU7832 15
MC2222 10
MC3021 40
PC1035 30
PC8888 50
PS1372 20
PS2091 108
PS2106 25
PS3333 15
PS7777 25
TC3218 40
TC4203 20
TC7777 20
Возможна вложенная ("гнездовая") группировка, при которой в предложении GROUP BY задается более одной колонки. При вложенной группировке набор результатов будет группироваться по каждой из колонок, участвующих в группировке, в том порядке, в котором были заданы колонки. Например, чтобы узнать средние цены книг, сгруппированных сначала по типу, а затем по издательству, можно выполнить такой запрос:
SELECT type, pub_id, AVG(price) AS "Средняя цена"
FROM titles
GROUP BY type, pub_id
GO
В набор результатов попадут 8 строк:
type pub_id Средняя цена
--------------------------------------------------
business 0736 2.99
psychology 0736 11.48
UNDECIDED 0877 NULL
mod_cook 0877 11.49
psychology 0877 21.59
trad_cook 0877 15.96
business 1389 17.31
popular_comp 1389 21.48
Обратите внимание, что книги, имеющие тип psychology и business, попали в набор результатов более одного раза, потому что они сгруппированы для разных идентификаторов издательств. Значение NULL, показанное в качестве средней цены книг типа UNDECIDED (нераспределенные), отражает тот факт, что для книг этого типа в таблицу не были введены их цены, поэтому невозможно вычислить среднюю цену.
Предложение GROUP BY можно применять с необязательным ключевым словом ALL, означающим, что в набор результатов должны быть включены все группы, даже не соответствующие условию поиска. Группы, не имеющие строк, соответствующих условию поиска, будут содержать в итоговой колонке значение NULL, поэтому их будет сразу видно. Например, чтобы узнать среднюю цену для книг, имеющих авторские отчисления 12%, а также показать в наборе результатов строки для книг, имеющих авторские отчисления не 12% (у них в итоговой колонке будет значение NULL), группируя книги сначала по типам, а затем по идентификатору издательства, выполните такой запрос:
SELECT type, pub_id, AVG(price) AS "Средняя цена"
FROM titles
WHERE royalty = 12
GROUP BY ALL type, pub_id
GO
В набор результатов попадут 8 строк:
type pub_id Средняя цена
-------------------------------------------------
business 0736 NULL
psychology 0736 10.95
UNDECIDED 0877 NULL
mod_cook 0877 19.99
psychology 0877 NULL
trad_cook 0877 NULL
business 1389 NULL
popular_comp 1389 NULL
Будут выведены строки для всех типов книг, но для типов книг, у которых не имеется книг с 12-процентными авторскими отчислениями, появится NULL.
Если мы уберем ключевое слово ALL, то набор результатов будет содержать информацию только для тех типов книг, у которых имеются книги с 12-процентными авторскими отчислениями. Набор результатов будет содержать 2 строки и будет таким:
type pub_id Средняя цена
---------------------------------------------------
psychology 0736 10.95
mod_cook 0877 19.99
Предложение GROUP BY часто применяется в сочетании с предложением HAVING, про которое мы сейчас вам расскажем.