Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Язык структурированных запросов и основы web-программирования. Учебное пособие
.pdf
Добавив названия продуктов в таблицу Sale, получим результат
полного внешнего объединения для таблиц Sale и Tovar (рис. 1.12).
Рис. 1.12. Полное внешнее объединение для таблиц Sale и Tovar
Чтобы получить только уникальные строки из обеих таблиц, необходимо использовать полное внешнее объединение, а затем исключить
строки, которые повторяются (рис. 1.13).
SELECT * FROM Table1 FULL JOIN Table2 on Table1.столбец =
Table2.столбец WHERE Table1.id IS NULL OR Table2.id IS NULL;
Рис. 1.13. Полное внешнее объединение
(только уникальные строки)
Результат полного внешнего объединения для случая, когда необходимы только уникальные строки для таблиц Sale и Tovar, показан на
рис. 1.14.
Рис. 1.14. Полное внешнее объединение (только уникальные строки)
для таблиц Sale и Tovar
11

В практических приложениях чаще всего необходимы данные сразу из нескольких таблиц. Извлечение данных из нескольких таблиц
является одной из самых полезных возможностей SQL. Извлекать все
данные сразу из всех таблиц требуется очень редко, поэтому лучше
объединять в запросе только те несколько таблиц, которые необходимы в каждом конкретном случае. Имена таблиц
для связывания указываются в списке ключевого слова FROM. Наиболее полезным типом
связывания является связывание по равенству, которое также называют внутренним связыванием.
Пример 1.1. Получить информацию о заказах из города Томска,
которые датируются до 2021-10-01. В этом случае можно воспользоваться указанной ниже командой.
Select * from zakaz inner join city on zakaz.idCity=city.idCity WHERE
city= 'Tomsk' and zakaz.DateZakaz< '2021-10-01';
Результат выполнения команды показан на рис. 1.15.
Рис. 1.15. Выборка из нескольких таблиц
Для подведения итогов по данным запроса могут применяться агрегатные функции, которые используются аналогично именам полей
в операторе SELECT, но они берут имя поля как аргумент. Функция
COUNT применяется для подсчета строк или значений в столбце, отличных от значения NULL. Совместно с опцией DISTINCT эта функция подсчитывает только разные строки. Если использовать
функцию
COUNT в виде COUNT(*), то в этом случае в результате получаем
полное количество строк, включая пустые значения.
Опция ALL противоположна опции DISTINCT. Синтаксис функ-
ции COUNT будет иметь вид, представленный ниже.
COUNT [ (*) | ( DISTINCT | ALL ) ] (имя_столбца)
Результат выполнения функции COUNT(*) приведен на рис. 1.16.
Рис. 1.16. Функция COUNT(*)
12

Функция SUM применяется для подсчета суммы значений в столбце. Эту функцию можно использовать вместе с ключевым словом
DISTINCT, при этом повторно встречающиеся значения в сумму не
включаются. В этом случае итоговое значение не будет полной суммой, так как некоторые строки не будут учитываться. Синтаксис функции SUM будет иметь вид, представленный
ниже.
SUM ( [ DISTINCT ] имя_столбца)
Функция AVG применяется для подсчета среднего значения. При
использовании вместе с ключевым словом DISTINCT повторно встречающиеся строки не учитываются. Синтаксис функции AVG будет
иметь вид, представленный ниже.
AVG ( [ DISTINCT ] имя_столбца)
Функции MAX и MIN используются для подсчета максимального
и минимального значения соответственно. Значения типа NULL при
этом игнорируются. Возможно совместное применение с ключевым
словом DISTINCT. Синтаксис функции MAX будет иметь вид, представленный ниже.
MAX ( [ DISTINCT ] имя_столбца)
Синтаксис функции MIN выглядит аналогично синтаксису функции MAX.
Пример 1.2. Найти максимальное, минимальное и среднее значение
стоимости товара. В этом случае можно воспользоваться указанной
ниже командой.
Select avg(cost), max(cost), min(cost) from tovar;
Результат выполнения команды показан на рис. 1.17.
Рис. 1.17. Использование агрегатных функций
Следует отметить, что использование подзапросов позволяет сделать работу с базой данных более эффективной. В качестве подзапроса
будем понимать запрос, содержащийся в выражении ключевого слова
WHERE другого запроса с целью дополнительных ограничений на выводимые данные.
13

Пример 1.3. Найти клиентов, у которых есть товары со стоимостью
больше, чем средняя стоимость товаров из города Омска. В этом случае можно воспользоваться командой, приведенной ниже.
Select client.FamClient, Tovar.cost, Zakaz.Datezakaz from zakaz inner
join client on zakaz.idClient=client.idClient inner join city on
zakaz.idCity=city.idCity inner join sale on zakaz.idZakaz=sale.idZakaz inner join tovar on sale.idProduct=tovar.idProduct WHERE Tovar.cost>
(Select avg(cost) from zakaz inner join client on
zakaz.idClient=client.idClient inner join city on zakaz.idCity=city.idCity
inner join sale on zakaz.idZakaz=sale.idZakaz inner join tovar on
sale.idProduct=tovar.idProduct WHERE city= 'Omsk');
Результат выполнения команды показан на рис. 1.18.
Рис. 1.18. Выполнение запроса
с учетом условий выполнения подзапроса
Таким образом, при использовании в запросе подзапроса сначала
реализуется подзапрос, а потом уже запрос с учетом условий выполнения подзапроса.
1.2. Массивы
Поля данных PostgreSQL вместо отдельных величин могут содержать конструкции, называемые массивами.
Чтобы создать простейшее поле-массив, необходимо включить
в команду CREATE TABLE или ALTER TABLE пару квадратных скобок после имени поля. Квадратные скобки показывают, что вместо одного значения в поле может храниться массив указанного типа.
Например, команда для создания поля single_array типа type выглядит
так:
single_array type[] – одномерный массив.
Дополнительные квадратные скобки определяют многомерные
массивы, т. е. «массивы массивов», например:
multi_array type[][] – многомерный массив.
14

Теоретически в квадратных скобках можно указать целое число,
чтобы созданный массив имел фиксированный размер, т. е. всегда состоял из п элементов по указанному измерению и не более.
Пример 1.4. Создать таблицу с полем-массивом, содержащим
названия книг. Команда, приведенная ниже, дает возможность создать
требуемую таблицу.
CREATE TABLE book2 (employee_id integer, books text[]);
Таблица позволяет хранить в одном
ство названий книг.
Многомерные массивы создаются аналогичным образом, только
за первой парой квадратных скобок добавляются дополнительные
пары.
Пример 1.5. Создать таблицу с полем, содержащим многомерный
массив. В результате выполнения команды, приведенной ниже, получаем требуемую таблицу.
CREATE TABLE f_book21 (employee_id integer, authors_and_titles
text[][]);
В этом примере создается таблица f_book21 с целочисленным полем employee_id и многомерным массивом
ски создается массив текстовых массивов.
Вставка значений в поля-массивы
В PostgreSQL предусмотрен специальный синтаксис вставки нескольких значений в одно поле, который основан на определении
массивов-констант. Кавычки нужны только при работе с массивами
строк. Таким образом, обобщенная форма массива-константы выглядит так:
'{ "текст" [, ...] }' – массив строк;
'{ число [, ...]}' –
Поле может определяться так же, как и массив произвольного типа
(включая типы boolean, date и time). Как правило, если для описания
величины в скалярном контексте должны использоваться апострофы,
в контексте массива эта величина заключается в кавычки.
числовой массив.
поле неограниченное количе-
author_and_titles. Фактиче-
15

Пример 1.6. Вставить данные с использованием массивов-констант.
Для выполнения этой операции можно воспользоваться командой,
приведенной ниже.
INSERT INTO book2 VALUES (1, '{"The Students Guide"}');
INSERT INTO book2 VALUES (2, '{"The Student1", "Student1,
Student2"}');
В этом примере в таблицу book2 вставляются две записи. Первая
команда создает массив с одним элементом для работника с кодом 1,
а вторая запись – массив с двумя элементами для работника с кодом 2.
В обеих командах INSERT
Даже при вставке одного элемента массив заключается в фигурные
скобки. Кроме того, апостроф в названии книги экранируется символом \, хотя и находится внутри кавычек. Это связано с тем, что массивконстанта сначала обрабатывается как одна длинная строка, а затем
интерпретируется как массив по контексту целевого поля.
При вставке
ключаются в отдельные фигурные скобки и разделяются запятыми.
Пример 1.7. Вставить данные в многомерный массив. Для выполнения этой операции можно воспользоваться командой, приведенной
ниже.
INSERT INTO f_book21 VALUES (1, '{{"Avtor1", "Kniga1"},
значений в многомерный массив все подмассивы за-
{"Avtor2", "Kniga2"}, {"Avtor3", "Kniga3"}}');
используются массивы-константы.
Многомерный массив в этом примере содержит три текстовых массива, каждый из которых состоит из двух элементов. Первые
каждого массива обозначают авторов, а вторые элементы – названия
книг, написанных этими авторами.
Выборка из полей-массивов
При выборке из поля-массива весь массив возвращается в формате
константы. На практике чаще требуется получить некоторое подмножество элементов. Для решения этой задачи необходимо познакомиться с такими понятиями, как индексы элементов и
16
срезы массивов.
элементы

Индексы элементов
К отдельным элементам можно обращаться при помощи индексов –
целых чисел, заключенных в скобки и описывающих позицию искомого элемента в массиве. В PostgreSQL индексация в массивах начинается с 1, а не с 0.
Пример 1.8. Осуществить выборку отдельного элемента массива.
Данную операцию можно выполнить с помощью указанной ниже
команды.
SELECT books[1] FROM book2;
Результат выполнения
команды показан на рис. 1.19.
Рис. 1.19. Выборка отдельного элемента массива
При указании индекса несуществующего элемента массива выборка возвращает NULL. Обычно для обработки таких ситуаций используется конструкция IS NOT NULL.
Пример 1.9. Выполнить операцию для предотвращения выборки
NULL в массивах. Это можно сделать с помощью команды, приведенной ниже.
SELECT books[2] FROM book2 WHERE books[2] IS NOT NULL;
Результат выполнения операции демонстрируется на рис. 1.20.
Запрос возвращает только название, а запись с NULL исключается
из выборки
в результате использования секции WHERE с проверкой
условия NOT NULL.
Рис. 1.20. Предотвращение выборки NULL
17

При выборке из многомерного массива за исходным индексом перечисляются дополнительные индексы.
Пример 1.10. Выполнить операцию выборки из многомерного массива. Ниже приведена соответствующая команда.
SELECT authors_and_titles[1][1] AS author, authors_and_titles[1][2]
AS title FROM f_book21;
В этом примере из таблицы f_book21 выбираются два элемента –
имя автора и название книги. На рис. 1.21 демонстрируется результат
выполнения команды.
Рис. 1.21. Выборка из многомерного массива
Срезы массивов
В PostgreSQL также поддерживается возможность создания срезов
при выборке из массива. Срез аналогичен обычному обращению
к элементам по индексу, но он описывает интервал значений. Срез
задается парой целочисленных индексов, разделенных двоеточием
и заключенных в квадратные скобки. Например, конструкция [2:5]
описывает второй, третий, четвертый и пятый элементы заданного массива. Результат среза
возвращается в виде константы-массива, которая
фактически описывает подмножество элементов исходного массива.
Пример 1.11. Выполнить операцию выборки с использованием среза. Ниже приведена соответствующая команда.
SELECT books[1:2] FROM book2;
В примере 1.11 выбираются первые два элемента массива books
в записях таблицы book2. На рис. 1.22 демонстрируется результат
выполнения команды.
Рис. 1.22. Выборка с использованием среза
18

Определение количества элементов
Чтобы узнать количество значений, хранящихся в массиве, следует
воспользоваться функцией array_dims(). В качестве параметра функции
передается идентификатор – имя поля-массива, для которого вызывается функция. Результат возвращается в виде строки, содержащей описание массива в синтаксисе среза.
Пример 1.12. Определить количество значений, хранящихся в массиве. Ниже приведен вызов соответствующей
функции.
SELECT array_dims(books) FROM book2;
На рис. 1.23 демонстрируется вызов функции array_dims() для поля
books таблицы book2.
Рис. 1.23. Функция array_dims()
Обновление данных в полях-массивах
Существует три варианта модификации данных в полях-массивах.
Полная модификация. Все содержимое массива заменяется
новыми данными, которые представлены в виде массива-константы.
Модификация среза. Срез, т. е. интервальное подмножество элементов, заменяется новыми данными, представленными в виде массива-константы. Количество элементов в
константе должно соответство-
вать количеству элементов в обновляемом срезе.
Модификация элемента. Отдельный элемент массива заменяется
новой константой, относящейся к базовому типу данных массива.
Элемент задается индексом.
Пример 1.13. Выполнить операцию полной модификации массива.
Ниже приведена соответствующая команда.
UPDATE book2 SET books='{"The Students Guide", "The Student4"}'
WHERE employee_id=1;
19

На рис. 1.24 демонстрируется результат выполнения команды
я
UPDATE, которая в примере 1.13 заменяет все текущее содержимое массива. Этот способ подходит и для модификации среза массива. Для этого
в конец идентификатора поля добавляется определение среза, например,
books[l:3] означает первый, второй и третий элементы массива.
Рис. 1.24. Полная модификация массива
На практике чаще возникает задача замены не всего массива и не
среза, а отдельных элементов. При обновлении отдельного элемента
к идентификатору поля присоединяется индекс, определяющий конкретный обновляемый элемент.
1.3. Работа с датами и временем
Продемонстрируем на конкретных примерах различные виды преобразования типов данных, применяемые в PostgreSQL. Исходные типы данных, используемые в работе, описывают дату и время. Приведем их краткое описание.
PostgreSQL поддерживает полный список SQL типов даты и времени (табл. 1.6).
Таблица 1.6
Типы даты/времени
Имя
timestamp [ (p) ] [ without time zone ] 8 байт Дата и время (без часового
timestamp [ (p) ] with time zone 8 байт Дата и время с часовым
date 4 байта Дата (без часового пояса)
time [ (p) ] [ without time zone ] 8 байт Только время (без даты)
time [ (p) ] with time zone 12 байт Время с часовым поясом
interval [ fields ] [ (p) ] 12 байт Интервал времени
Размер
хранения
20
пояса)
по
сом
Описание
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
