Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Язык структурированных запросов и основы web-программирования. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
1 Мб
Скачать
☆
Добавив названия продуктов в таблицу 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 in­ner 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
пояса)
по
сом
Описание
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]