Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Базы данных. Практический курс. В 2 частях. Ч.1. Объектно-реляционные базы данных на примере PostgreSQL 9.5. Учебное пособие.pdf
X
- •Введение
- •Контрольные вопросы
- •Создание базы данных
- •Создание таблиц
- •Создание последовательностей
- •Ввод данных
- •Оператор CREATE TABLE
- •Оператор ALTER TABLE
- •Операторы DROP TABLE и DROP
- •Создание индексов
- •Контрольные вопросы
- •Средства определения данных языка SQL
- •Средства запроса данных языка SQL
- •Чтение заданных столбцов из одиночной таблицы
- •Чтение заданных строк из одиночной таблицы
- •Чтение заданных строк и столбцов из одиночной таблицы
- •Сортировка результатов
- •Агрегатные функции и группировка
- •Оконные функции
- •Чтение данных из нескольких таблиц с применением вложенных запросов
- •Чтение данных из нескольких таблиц с помощью операции соединения
- •Объединения
- •Средства модификации данных языка SQL
- •Вставка данных, оператор INSERT
- •Изменение данных, оператор UPDATE
- •Удаление данных, оператор DELETE
- •Транзакции
- •SQL-представления
- •Использование представлений для скрытия столбцов и строк
- •Использование представлений для отображения вычисляемых столбцов
- •Использование представлений для скрытия сложного синтаксиса
- •SQL-запросы в прикладных программах
- •Хранимые процедуры
- •Триггеры
- •Использование триггеров для проверки допустимости вводимых данных
- •Триггер, обновляющий представление
- •Триггер, обеспечивающий ссылочную целостность
- •Модуль TABLEFUNC
- •Словарь метаданных
- •Контрольные вопросы
- •Функция ROW_NUMBER
- •Функция COALESCE
- •Числовые функции
- •Тригонометрические функции
- •Контрольные вопросы
- •Заключение
- •Библиографический список

Глава 3. Введение в язык SQL 3.2. Средства запроса данных языка SQL
Результатом первого запроса будет отношение
Count
8
Результатом второго запроса будет отношение
Count
5
Разница в результатах возникает потому, что второй оператор
SELECT не учитывает повторяющиеся строки.
Вот еще один пример использования агрегатных функций:
SELECT MIN(SalesPrice), MAX(SalesPrice), SUM(SalesPrice)
FROM TRANSACTION
WHERE TransactionID < 406;
Результатом будет следующая таблица:
Min Max Sum
9750.00 73500.00 165950.00
Кроме случая с использованием ключевых слов GROUP BY и
PARTITION BY (см. далее), Имена столбцов не могут смешиваться с
агрегатными функциями. Например, следующий оператор недопустим:
SELECT CustomerID, SUM(SalesPrice)
FROM TRANSACTION
WHERE TransactionID < 406;
3.2.7 Агрегатные функции и группировка
Полезность агрегатных функций увеличивает тот факт, что их
можно применять к группам строк данных. Например, следующий
оператор подсчитывает количество художников каждой национальности:
SELECT Nationality, COUNT(*)
FROM ARTIST
GROUP BY Nationality;
Результат будет таким:
51

3.2. Средства запроса данных языка SQL Глава 3. Введение в язык SQL
Nationality Count
German 1
French 2
Russian 1
US 3
Spanish 1
Ключевое слово GROUP BY предписывает СУБД отсортировать
таблицу по указанному столбцу, а затем применить агрегатные
функции к группам строк, имеющим одинаковые значения данного
столбца. При использовании GROUP BY имя столбца, по которому
производится группировка, и агрегатные функции могут сосуществовать в предложении SELECT. Это первый из двух случаев, когда
имя столбца может появляться вместе с агрегатными функциями.
Далее ограничить множество выдаваемых результатов можно,
применяя к формируемым группам различные условия. Например,
если нас интересуют только те группы, в которых имеется более
одной записи, мы могли бы написать следующее:
SELECT Nationality, COUNT(*)
FROM ARTIST
GROUP BY Nationality
HAVING COUNT(*) > 1;
Результатом этого оператора будет следующая таблица:
Nationality Count
French 2
US 3
Вместе с ключевым словом GROUP BY можно использовать и
предложение WHERE. Однако здесь имеет место неоднозначность.
Если условие в предложении WHERE применяется до формирования
групп, результат будет иным, чем когда это условие применяется
к уже сформированным группам. Для устранения этой неоднозначности стандарт SQL устанавливает, что в случаях, когда предложения WHERE и GROUP BY используются одновременно, первым должно
применяться условие, записанное в предложении WHERE. Рассмотрим, например, следующий оператор:
52

Глава 3. Введение в язык SQL 3.2. Средства запроса данных языка SQL
SELECT Nationality, COUNT(*)
FROM ARTIST
WHERE ArtistID < 106
GROUP BY Nationality
HAVING COUNT(*) > 1;
При выполнении данного оператора сначала применяется
условие из предложения WHERE, которое отбирает художников, чей
идентификатор меньше 106. Затем, после формирования групп,
применяется условие из предложения HAVING. Результат имеет следующий вид:
Nationality Count
US 2
3.2.8 Оконные функции
Использование оконных функций – второй из двух случаев,
когда имя столбца может появляться вместе с агрегатными функциями.
При использовании группировки результирующая таблица содержит по одной строке для каждого группируемого значения, а
оконная функция не свертывает результаты, принадлежащие одной
группе.
Следующий запрос использует оператор GROUP BY:
SELECT Title, ArtistID, COUNT(*)
FROM WORK
GROUP BY Title, ArtistID
ORDER BY ArtistID;
Результат имеет вид:
Title ArtistID Count
Mi Vida 101 1
Mystic Fabric 106 2
Slow Embers 106 1
Northwest by Night 108 1
Следующий запрос содержит оператор PARTITION BY для реализации оконной функции и имеет вид:
53

3.2. Средства запроса данных языка SQL Глава 3. Введение в язык SQL
SELECT Title, ArtistID, COUNT(*)
OVER (PARTITION BY ArtistID)
FROM WORK
ORDER BY ArtistID;
Результат данного запроса представлен в таблице:
Title ArtistID Count
Mi Vida 101 1
Mystic Fabric 106 3
Slow Embers 106 3
Mystic Fabric 106 3
Northwest by Night 108 1
Как видно из примеров, оператор PARTITION BY является близким аналогом оператора GROUP BY, но вместо группировки результатов по столбцам, указанным в запросе вне агрегатных функций, что
приводит к уменьшению общего количества строк в результирующей таблице, данный оператор возвращает результаты вычисления
агрегатных функций.
3.2.9 Чтение данных из нескольких таблиц с применением вложенных запросов
Все запросы, рассмотренные ранее, считывали данные из одиночной таблицы. Бывает, однако, что для получения требуемой
информации необходимо обработать более одной таблицы. Предположим, например, что мы хотим знать названия работ, которые
были проданы галереей дороже 20 000. Названия работ хранятся в
таблице WORK, а стоимости продаж в таблице TRANSACTION.
Если бы мы знали, что дороже 20 000 были проданы работы
с номерами 301, 302 и 305, мы могли бы получить названия этих
работ с помощью следующего запроса:
SELECT Title
FROM WORK
WHERE WorkID IN (301, 302, 305);
Но в том-то и дело, что в условии задачи номера работ нам не
заданы. Ничто, однако, не мешает нам узнать эти номера, инициировав следующий запрос:
54

Глава 3. Введение в язык SQL 3.2. Средства запроса данных языка SQL
SELECT DISTINCT WorkID
FROM TRANSACTION
WHERE SalesPrice > 20000;
Результатом будет таблица:
WorkID
301
305
302
Теперь мы можем объединить эти два SQL-запроса при помо-
щи так называемого вложенного запроса (subquery):
SELECT Title
FROM WORK
WHERE WorkID IN (
SELECT DISTINCT WorkID
FROM TRANSACTION
WHERE SalesPrice > 20000
);
Результатом этого оператора будет следующее:
WorkID
Mystic Fabric
Mi Vida
Northwest by Night
И действительно, здесь мы видим названия работ, которые
были проданы галереей дороже 20 000. Подобным образом вложенность запросов может быть расширена до трех, четырех и более
уровней.
3.2.10 Чтение данных из нескольких таблиц с помощью операции соединения
Вложенные запросы подходят для обработки нескольких таблиц до тех пор, пока результаты (столбцы в предложении SELECT)
относятся к одной и той же таблице. Если же нам нужно извлечь
данные из двух или более таблиц, при помощи вложенного запроса это сделать не удастся. Вместо этого необходимо использовать
операцию соединения (JOIN).
55

3.2. Средства запроса данных языка SQL Глава 3. Введение в язык SQL
Основная идея здесь – создать новое отношение, связав между
собой содержимое двух или более исходных отношений. Рассмотрим следующий пример:
SELECT Title, SalesPrice
FROM WORK, TRANSACTION
WHERE WORK.WorkID = TRANSACTION.WorkID;
Смысл этого оператора заключается в том, что создается новая таблица с двумя столбцами Title и SalesPrice. Эти столбцы
берутся соответственно из таблиц WORK и TRANSACTION при условии,
что столбец WorkID в таблице WORK равен одноименному столбцу в
таблице TRANSACTION. Обозначения WORK.WorkID и TRANSACTION.WorkID
необходимы для устранения конфликта имен столбцов.
Эту операцию можно представить себе следующим образом.
Начнем с первой строки таблицы TRANSACTION. Возьмем значение
столбца WorkID в данной строке (в табл. 2.4 это 301) и просмотрим
строки таблицы WORK (табл. 2.3). Найдя в таблице WORK строку, где
WorkID также равняется 301, соединим столбец Title только что
найденной первой строки таблицы WORK со столбцом SalesPrice первой строки таблицы TRANSACTION.
Первая строка таблицы WORK (см. табл. 2.3) имеет WorkID, равный 301, поэтому мы соединяем столбец Title первой строки таблицы WORK со столбцом SalesPrice первой строки таблицы TRANSACTION,
и получаем тем самым первую строку соединения:
Title SalesPrice
Mystic Fabric 18500.00
Теперь, по-прежнему используя равенство WorkID = 301, найдем следующую строку в отношении WORK, которая имеет WorkID,
равный 301. Таких строк больше нет, поэтому переходим ко второй
строке таблицы TRANSACTION. Так как в этой строке WorkID так же
равен 301, снова найдем первую строку в отношении WORK, которая
имеет WorkID, равный 301. Соединив столбец Title первой строки таблицы WORK со столбцом SalesPrice второй строки таблицы
TRANSACTION, мы получим вторую строку соединения:
56

Глава 3. Введение в язык SQL 3.2. Средства запроса данных языка SQL
Title SalesPrice
Mystic Fabric 18500.00
Mystic Fabric 46700.00
Таким образом, перебирая все строки отношения TRANSACTION,
получаем окончательный результат:
Title SalesPrice
Mystic Fabric 18500.00
Mystic Fabric 46700.00
Mystic Fabric 9750.00
Mi Vida 17500.00
Mi Vida 73500.00
Slow Embers 14500.00
Mystic Fabric
Northwest by Night 71500.00
Таблицу, получившуюся в результате соединения, можно обрабатывать также, как и любую другую таблицу. Например, мы можем сгруппировать строки по названиям картин и просуммировать
вырученные суммы по каждой из картин. Это сделает следующий
запрос:
SELECT Title, SUM(SalesPrice)
FROM WORK, TRANSACTION
WHERE WORK.WorkID = TRANSACTION.WorkID
GROUP BY Title;
Результатом будет следующая таблица:
Title Sum
Mi Vida 91000.00
Slow Embers 14500.00
Northwest by Night 71500.00
Mystic Fabric 74950.00
Предложение WHERE мы также можем применить в процессе
создания соединения:
SELECT Title, SalesPrice
FROM WORK, TRANSACTION
WHERE WORK.WorkID = TRANSACTION.WorkID
AND SalesPrice > 20000;
57

3.2. Средства запроса данных языка SQL Глава 3. Введение в язык SQL
Результат соединения будет таким:
Title SalesPrice
Mystic Fabric 46700.00
Mi Vida 73500.00
Northwest by Night 71500.00
Это такая же таблица, поэтому все описанные выше
SQL-операторы к ней применимы.
Теперь рассмотрим случай, когда требуется соединить три
таблицы. Предположим, нам нужно знать по каждой картине вырученную сумму и имя художника. Для этого нам нужно соединить три таблицы: TRANSACTION (поле SalesPrice), WORK (поле Title) и
ARTIST (поле Name):
SELECT Title, SalesPrice, Name
FROM WORK, TRANSACTION, ARTIST
WHERE WORK.WorkID = TRANSACTION.WorkID
AND WORK.ArtistID = ARTIST.ArtistID;
Результатом соединения будет следующая таблица:
Title SalesPrice Name
Mystic Fabric 46700.00 Tobey
Mystic Fabric 18500.00 Tobey
Mi Vida 73500.00 Miro
Mi Vida 17500.00 Miro
Slow Embers 14500.00 Tobey
Mystic Fabric Tobey
Mystic Fabric 9750.00 Tobey
Northwest by Night 71500.00 Chagall
В стандарте SQL-92 введен альтернативный синтаксис соединения, ставший весьма популярным, поскольку его легче интерпретировать. Здесь вместо WHERE используются ключевые слова JOIN и
ON:
SELECT Title, SalesPrice
FROM WORK JOIN TRANSACTION
ON WORK.WorkID = TRANSACTION.WorkID;
Результат имеет следующий вид:
58

Глава 3. Введение в язык SQL 3.2. Средства запроса данных языка SQL
Title SalesPrice
Mystic Fabric 46700.00
Mystic Fabric 18500.00
Mi Vida 73500.00
Mi Vida 17500.00
Slow Embers 14500.00
Mystic Fabric
Mystic Fabric 9750.00
Northwest by Night 71500.00
Сделать оператор соединения более удобным для чтения мож-
но, используя псевдонимы для имен таблиц. Выражение FROM WORK
W присваивает таблице WORK псевдоним W. Это позволяет переписать
предыдущий оператор следующим образом:
SELECT Title, SalesPrice
FROM WORK W JOIN TRANSACTION T
ON W.WorkID = T.WorkID;
Соединение трех таблиц можно выполнить путем добавления
предложения JOIN в конец первого оператора SELECT:
SELECT W.Title, SalesPrice, A.Name
FROM WORK W JOIN TRANSACTION T
ON W.WorkID = T.WorkID
JOIN ARTIST A
ON W.ArtistID = A.ArtistID;
Следует обратить внимание, что когда требуется указать имя
столбца в первой строке оператора SELECT, необходимо использовать псевдоним, а не имя таблицы. Так, в вышеприведенном операторе SELECT используется запись W.Title, а не WORK.Title.
По мере того как запросы усложняются, этот формат оказывается легче интерпретировать, и именно он будет использоваться
для соединений далее. На практике необходимо знать оба формата,
поскольку и тот, и другой применяются в промышленности.
Теперь рассмотрим различия между вложенным запросом и
соединением. На практике соединение во многих случаях можно
использовать в качестве альтернативы вложенным запросам. Например, ранее в пункте 3.2.9 был использован вложенный запрос
для нахождения названия работ, которые были проданы галереей
59

3.2. Средства запроса данных языка SQL Глава 3. Введение в язык SQL
дороже 20 000. Этот же запрос можно реализовать и с помощью
соединения:
SELECT DISTINCT Title
FROM WORK JOIN TRANSACTION
ON WORK.WorkID = TRANSACTION.WorkID
AND SalesPrice > 20000;
Хотя ситуации, когда соединение можно использовать вместо
вложенного запроса, нередки, такая замена все же возможна не
всегда. Например, соединения не могут заменить коррелированные
вложенные запросы, а также запросы с использованием ключевых
слов EXISTS и NOT EXISTS (будут рассматриваться далее в следующих
разделах пособия).
И наоборот, не всегда вложенный запрос может служить заменой для соединения. В соединении запрашиваемые столбцы могут принадлежать любой из соединяемых таблиц, а во вложенном
запросе все возвращаемые столбцы должны принадлежать только
одной таблице, и именно той, которая указана в предложении FROM
самого первого оператора SELECT. Например, в следующем вложенном запросе в результат войдут только столбцы таблицы ARTIST:
SELECT DISTINCT Name
FROM ARTIST
WHERE ArtistID IN (
SELECT ArtistID
FROM WORK
WHERE WorkID IN (
Select WorkID
FROM TRANSACTION
WHERE SalesPrice > 20000
)
);
Если нужно включить в результат столбец WORK.Title, придется использовать соединение:
SELECT A.Name, W.Title
FROM ARTIST A JOIN WORK W
ON A.ArtistID = W.ArtistID
JOIN TRANSACTION T
ON T.WorkID = W.WorkID
AND SalesPrice > 20000;
60
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
