Лабораторная работаx

реклама
Лабораторная работа « Основы языка SQL»
Задание: Описать сформулированные Вами запросы, используя описанный
ниже аппарат.
Отчет: 1) Документ WORD 2003, содержащий для каждого запроса:
название, имя запроса в БД, формулировку на SQL, иллюстрация
результата запроса (как в данном документе). 2) База данных
в ACCESS 2003 с созданными запросами.
Введение
SQL — это язык структурированных запросов (Structured Query Language) к
реляционным базам данных. История SQL тесно связана с историей развития
реляционных баз данных. В 1974-1975 годах был создан первый прототип
реляционной СУБД. Кроме разработки самой СУБД, в рамках проекта System/R
в компании IBM проводилась работа над созданием языка запросов к базам
данных. Первый язык запросов получил название SEQUEL —
Structured English Query Language. Вторая реализация проекта System/R была
установлена на компьютерах нескольких заказчиков IBM с целью опытной
эксплуатации в 1978-1979 гг. В этой реализации язык запросов имел уже
название SQL, но до сих пор еще можно услышать от пользователей старое
название этого языка.
В 1982 году компания IBM начала поставки на рынок коммерческого продукта
SQL/Data System, а в 1983 году объявила о создании версии
SQL/Data System для операционной системы VM/CMS. В 1983 году IBM
выпустила новую реляционную СУБД — Database 2 (DB2). Благодаря влиянию
компании IBM на рынок вычислительных систем SQL DB2 стал фактическим
стандартом языка баз данных.
Во
второй
половине
восьмидесятых
годов
резко
увеличилась
производительность реляционных СУБД и с развитием реляционных
технологий связывались большие надежды. Появились, в частности, новые
версии СУБД Ingress и Oracle с производительностью, в два-три раза
превышающей
производительность
предыдущих
версий.
Росту
производительности
СУБД
способствовало
и
увеличение
общего
быстродействия компьютеров.
Опубликование в 1986 году стандарта SQL (ANSI/ISO) официально утвердило
SQL как стандартный язык реляционных СУБД. С появлением более мощных
персональных компьютеров и объединением их в локальные сети возникла
необходимость в новых СУБД. Поставщики таких СУБД снова стали
ориентироваться на SQL-технологии. И, наконец, SQL стал ключевой частью
архитектуры клиент/сервер.
Первоначально SQL фирмы IBM имел простой синтаксис, но на протяжении
нескольких лет производители программного обеспечения в области систем
управления базами данных добавляли к своим реализациям новые
возможности, многие из которых вошли в стандарты ANSI SQL. Версия языка
ANSI
SQL
была
принята
организацией International Standards Organization (ISO), отделением ООН со
штаб-квартирой
в
Женеве
и
комитетом International Electrotechnical Commission (IEC)
как
продукт
ISO/IEC9075:1992 или язык баз данных SQL (SQL-92). Отдельный стандарт
ANSI X.3.168-1989 определяет встроенный язык баз данных SQL(SQL-89).
Современные СУБД поддерживают SQL-89 и многие дополнения из SQL-92.
Кроме того, большинство СУБД имеют свои ключевые SQL-слова для создания
патентованных диалектов SQL, таких как Transact-SQL (сервера SQL Server)
или SQL Jet.
Мы будем использовать SQL Jet и Transact-SQL, не уделяя внимания их
отличиям от ANSI SQL-92.
Отметим, что историческое название SQL не совсем точно отражает суть этого
языка, поскольку он давно уже предназначен не только для построения
запросов (если, конечно, под «запросом» понимать только извлечение
информации из базы данных). Сейчас SQL позволяет реализовать все функции
СУБД: организацию данных, извлечение информации, модификацию данных,
управление доступом, совместное использование данных, обеспечение
целостности данных.
Типы команд SQL
В ANSI SQL имеется шесть основных типов команд:
□ команды языка определения данных (data definition language — DDL)
позволяют создавать новые таблицы в базе данных, добавлять индексы и т.д.;
основными командами языка определения данных являются:
CREATE TABLE
ALTER TABLE
DROP TABLE
CREATE INDEX
ALTER INDEX
DROP INDEX
Создать таблицу
Модифицировать таблицу
Удалить таблицу
Создать индекс
Модифицировать индекс
Удалить индекс
□ команды языка обработки данных (data manipulation language — DML)
используются для добавления, корректировки и удаления строк в таблицах и
включают команды:
INSERT
UPDATE
DELETE
Вставить данные в таблицу
Обновить данные
Удалить данные
□ команда языка запросов данных (data query language — DQL)
(единственная команда) используется для получения данных из таблиц и
определения формы представления этих данных:
SELECT
Выполнить запрос из таблиц базы
□ команды языка управления данными (data control language — DCL)
определяют доступ отдельных пользователей и групп пользователей к объектам
базы данных посредством полномочий, предоставляемых и отменяемых
командами:
GRANT
Предоставить привилегии
REVOKE
Отменить привилегии
□ команды языка обработки транзакций (transaction processing language —
TPL) обеспечивают обновление всех строк, используемых в операторе DML, и
включают следующие команды:
BEGIN TRANSACTION
COMIT TRANSACTION
SAVE TRANSACTION
Начать транзакцию
Завершить транзакцию
Создать точку сохранения
внутри транзакции
□ команды языка управления курсором (cursor control language — CCL)
выполняют операции с отдельными строками одной или нескольких таблиц и
включают команды: DECLARE CURSOR, FETCH INTO и UPDATE WHERE
CURRENT.
Создатели СУБД, в общем-то, не обязаны поддерживать все команды SQL92, и можно с уверенностью утверждать, что, практически, нет ни одной
коммерческой СУБД, в которой реализованы все команды SQL-92. В
частности, в SQL Jet не поддерживаются никакие зарезервированные слова
команд DCL и CCL.
SQL в MS ACCESS
В MS ACCESS SQL применяется в основном для выполнения запросов, хотя
очень удобно также удалять, добавлять и обновлять записи баз данных.
Используя SQL-запросы, можно выбирать из таблиц базы данных только
необходимые записи. При этом мы можем получить доступ не просто к одной
таблице, а к сложной выборке из связанных между собой таблиц или наборов
данных.
SQL-запросы можно также применять в приложениях, использующих
объектные модели DAO, RDO или ADO. Кроме того, SQL как стандартный
способ управления базами данных реализован во многих СУБД, включая
Microsoft Access и SQL Server.
Инструкция SELECT
Для работы с базами данных в Microsoft Access применяется язык запросов,
включающий единственную инструкцию SELECT. Рассмотрим некоторые
вопросы, связанные с ее использованием. Синтаксис (неполный) инструкции
SELECT в SQL Jet следующий:
SELECT [ALL | DISTINCT | DISTINCTROW | TOP] {* | table.*
| [ table. ] field1 [AS alias1] [, table. ]field2 [AS alias2] [, …] ]
}
FROM table1 [table1Alias] [table2 [table2Alias]] [, …]
[ IN externaldatabase ]
[WHERE criteria]
[GROUP BY groupfieldlist ]
[HAVING groupcriteria ]
[ORDER BY field1 [ ASC | DESC ] [field2 [ ASC | DESC ] [,…]]]
[WITH OWNERACCESS OPTION]
Инструкция SELECT включает следующие основные элементы:
□ SELECT означает, что из некоторых таблиц базы данных необходимо
выбрать набор (таблицу данных).
□
Необязательные
слова ALL, DISTINCT, DISTINCTROW и ТОР называются предикатами
(predicates) и определяют выбор следующим образом:
ALL указывает, что в набор передаются все строки (даже с дублируемыми
значениями);
DISTINCT указывает, что в набор передаются только сдублированные
строки;
DISTINCTROW указывает, что в результирующий наборбудет включена
каждая строка, в которой есть отличие в значении любого из полей исходных
таблиц (а не только полей, указанных для отображения в операторе SELECT);
ТОР используется для отображения некоторого количества (точного или в
процентном отношении) начальных или конечных записей из результирующего
набора.
□ Список {*
| table.*
[, table. ] field2 [AS alias2]
[,
| [ table. ] field1 [AS alias1]
…] ] } (фигурные скобки здесь
обозначают список) состоит из имен полей таблиц(ы) запроса.
Звездочка (*) означает выбор всех полей таблицы. Если в запросе указывается
несколько таблиц, то для определения поля используется наименование
таблицы, отделяемое от имени поля точкой (.). Поле может получать
«алиасное» имя (псевдоним) при помощи ключевого слова AS.
□ После слова FROM указываются таблицы, из которых выбираются ранее
указанные поля. Здесь table1 (,table2) — это имя таблицы (или таблиц),
содержащей данные, externaldatabase — имя базы данных, если не
используется текущая база.
Неотмеченные элементы инструкции SELECT мы будем рассматривать по мере
изучения более сложных запросов к таблицам.
Для примеров использования SELECT будем работать с базой
данных Lab 3.mdb, создание и заполнение которой рассматривалось в
предыдущей лабораторной работе.
Изучать инструкции
приложениях Access.
SELECT,
как
и
другие
инструкции,
можно
в
Последнее замечание перед тем, как начать рассмотрение SQL-инструкций,
касается способа записи этих инструкций в строке. Нет никаких правил
написания SQL-инструкций относительно их положения в строке. Можно
писать инструкцию в одной строке, можно — в нескольких.
Будем следовать следующему правилу: каждое предложение типа SELECT,
FROM, WHERE и т.д. будет начинаться с новой строки. Если будет
необходимо, на новой строке будет выполнен отступ. Так SQL-инструкции
удобнее записывать, так их легче понимать.
Для тестирования SQL-инструкций в среде Access выберите в левой части
главного окна Access в меню Объекты опцию Запросы и дважды щелкните
команду Создание запроса в режиме конструктора. Появившееся
окно Добавление таблицы нам в данном случае не нужно, поэтому его следует
закрыть.
Не обращая внимания на рассмотренные в предыдущей лабораторной работе
средства Access, предназначенные для создания запросаQBE, выберите
команду Режим SQL в меню Вид (рис. 3.1), чтобы, наконец, получить доступ к
тому окну, в котором можно будет набирать SQL-инструкции.
Рисунок 3.1 Выбор команды Режим SQL
Инструкцию SELECT будем изучать по принципу «от простого — к
сложному»: сначала выбросим из полного синтаксиса этой инструкции все
необязательные элементы, а затем постепенно будем использовать их, получая
более сложные запросы. Если отбросить все необязательные предложения из
списка {*
| table.*
| [ table. ] field1 [AS alias1]
[, table. ] field2 [AS alias2] [, …] ] } и оставить только элемент *, то
получим самый простой вариант SELECT-инструкции (SQL-запроса), который
будет иметь вид (рис 3.2):
SELECT * FROM Продукты;
Рисунок 3.2 Простейший запрос на SQL
Результат показан на рис. 3.3.
Рисунок 3.3. Результат выполнения простейшего запроса
Выбор в SQL-запросе определенных полей
Чаще всего вам не нужно будет получать набор со всеми полями одной (или
более) таблицы. Например, поскольку поле КодПрод в таблице Продукты
предназначено в основном для связи с другими таблицами, то не часто его
следует включать в SQL-запрос. В SELECT-инструкции можно указать
конкретные наименования используемых полей некоторой таблицы.
Например;
SELECT Продукт, ЕдИзм
FROM Продукты;
Для изменения запроса используем команду Режим SQL в меню Вид (рис. 3.1)
Результат запроса показан на рис 3.4.
Рисунок 3.4. Выбор определенных полей
При этом можно изменить заголовки:
SELECT Продукт AS [Наименование
измерения]
продукта], ЕдИзм AS [Единица
FROM Продукты;
Результат см. на рис. 3.5.
Рисунок 3.5. Запрос с измененными заголовками выбранных полей
Выбор в SQL-запросе определенных записей
Ключевое слово WHERE в синтаксисе инструкции SELECT позволяет
указывать определенные типы записей, которые должны попадать в набор.
Например:
SELECT Продукт AS [Наименование
измерения]
продукта], ЕдИзм AS [Единица
FROM Продукты
WHERE ЕдИзм = "л";
Результат выборки показан на рис. 3.6.
Рисунок 3.6 Запрос с записями, удовлетворяющими заданному условию
В области слова WHERE можно располагать сложное условное выражение с
использованием знаков логических операций и функций. Например:
SELECT НаимТовара as [Наименование
товара],
закупочная]
FROM Товары WHERE Цена1 > 50 AND Цена1 < 200;
Цена1 as [Цена
или
SELECT НаимТовара as [Наименование
закупочная]
товара],
Цена1 as [Цена
FROM Товары
WHERE Цена1 > 50 AND Len (НаимТовара) < 20;
В первом случае запрашиваются товары, оптовая цена которых находится в
диапазоне оптовых цен (55-200), а во втором — цены которых больше 50
денежных единиц и длина наименования не превышает 20 символов.
Кроме
операций < и >,
в
инструкции SELECT можно
использовать
операции = (равно), <= (меньше или равно) и >= (больше или равно), а
также AND, OR и NOT. Но еще большие возможности по отбору необходимых
записей предоставляют такие операторы, как IS NULL,BETWEEN, IN и LIKE.
Оператор IS NULL позволяет найти в таблице записи, в полях которых не
указаны данные, например:
SELECT НаимТовара AS [Наименование
закупочная]
товара],
Цена1 AS [Цена
FROM Товары
WHERE Цена2 IS NULL OR Цена1 < 50;
Оператор BETWEEN позволяет указать диапазон, в котором находятся данные
некоторого поля, например:
SELECT НаимТовара as [Наименование
закупочная]
товара],
Цена1 as [Цена
FROM Товары
WHERE Цена1 BETWEEN 42 AND 120;
Оператор IN позволяет указать список, в котором находятся данные некоторого
поля, например:
SELECT НаимТовара as [Наименование
закупочная]
товара],
Цена1 as [Цена
FROM Товары
WHERE Цена1 IN (42, 105,750)
В SQL-инструкции можно также использовать оператор LIKE, например
инструкция:
SELECT НаимТовара as [Наименование
закупочная]
товара],Цена1 as [Цена
FROM Товары
WHERE НаимТовара LIKE "(VCD)*";
позволяет получить только те записи, у которых в наименовании первые пять
символов совпадают со строкой "(VCD)".
Оператор LIKE можно использовать для контекстного поиска, например, если
пользователь введет текстовую строку, содержащую часть наименования
товара, то эту строку легко использовать в виде шаблона. Следующая
инструкция выполняет поиск записей, в которых наименование содержит в
качестве подстроки строку "мишень":
SELECT НаимТовара as [Наименование
закупочная]
товара],
Цена1 as
[Цена
FROM Товары
WHERE НаимТовара LIKE "*мишень*";
Оператор NOT, который инвертирует логическое выражение, может
использоваться с операторами IS NULL, BETWEEN, IN, LIKE. При этом,
практически, речь идет об операторах IS NOT NULL, NOT BETWEEN, NOT
IN и NOT LIKE, например, как в следующих четырех инструкциях:
SELECT НаимТовара AS
[Цена закупочная]
[Наименование
товара],
Цена! AS
FROM Товары
WHERE Цена2 IS NOT NULL OR Цена1 < 50;
SELECT НаимТовара as [Наименование
закупочная]
товара],
Цена1 as [Цена
FROM Товары
WHERE Цена1 NOT BETWEEN 42 AND 120;
SELECT НаименованиеТовара as [Наименование
Цена! as [Цена закупочная]
товара],
FROM Товары
WHERE Цена1 NOT IN (42, 105,750);
SELECT НаимТовара as [Наименование
закупочная]
товара],
Цена1 as [Цена
FROM Товары
WHERE НаимТовара NOT LIKE "(VCD)*";
Результирующие данные запроса можно форматировать с использованием,
например, функции Format. В следующем запросе данные форматируются при
помощи строки "### ##0.00$":
SELECT НаимТовара as [Наименование товара],
Format(Цена1*1.2,"### ##0.00р") as [Цена оптовая]
FROM Товары
WHERE Цена1 < 100
Обратите внимание еще и на то, что функция Format в качестве первого
аргумента получает произведение Цена1*1.2. Таким образом, мы получаем
другую цену из некоторой базовой.
Для форматирования выводимых в запросе данных можно использовать
функции преобразования строк. Например, в следующем запросе наименования
товаров выводятся символами верхнего регистра, поскольку здесь
используется функция StrConv:
SELECT StrConv(Продукт,1) AS [Наименование
продукта], ЕдИзм AS [Единица измерения]
FROM Продукты;
Результат такого запроса показан на рис. 3.7.
Рисунок 3.7. Результат запроса с указанием формата представления информации
Выбор данных из более чем одной таблицы
Рассмотрим задачу выбора из базы данных товаров некоторого склада. Перед
тем как рассмотреть использование слова WHERE для связи таблиц, заметим,
что в инструкции SELECT можно перед именем поля указывать имя
таблицы, которое отделяется от имени поля точкой:
SELECT { * |
alias2] [, ...]]}
[table1.]field1
FROM table1 [table1Alias]
iteria]
Например (Запрос 6):
[AS alias1]
[, [table2.]field2
[AS
[, table2 [table2Alias] [, ...] [WHERE cr
SELECT Продукты.Продукт AS [Наименование
продукта], Продукты.ЕдИзм AS [Единица измерения]
FROM Продукты;
Или (Запрос 7)
SELECT tab.Продукт AS [Наименование
продукта], tab.ЕдИзм AS [Единица измерения]
FROM Продукты tab;
Во второй инструкции использовано альтернативное имя таблицы (локальный
псевдоним), но обе инструкции выдают один и тот же результирующий набор.
Следующая инструкция позволяет получить наименования (из таблицы
Продукты) и количества (из таблицы Продажи) продуктов (результат
выполнения — на рис. 3.8):
SELECT Продукты.Продукт AS [Наименование
продукта], Продажи.Количество AS [Количество]
FROM Продукты, Продажи
WHERE Продукты.КодПрод = Продажи.КодПрод;
Рисунок 3.8. Выборка из двух таблиц
Обратите
внимание
выражение Продукты.КодПрод = Продажи.КодПрод.
на
Именно оно используется для связи таблиц Продукты и Продажи по ключевому
полю КодПрод.
Результат
выполнения
предыдущей
инструкции
напоминает
инвентаризационную ведомость без указания даты продажи. Следующая
инструкция позволяет получить наименования и количества только для тех
продуктов, которые проданы после заданной даты (рис. 3.9):
SELECT Продукты.Продукт AS [Наименование
продукта], Продажи.Количество AS [Количество]
FROM Продукты, Продажи
WHERE Продажи.ДатаПродажи >
#3/25/2003# AND Продукты.КодПрод = Продажи.КодПрод;
Рисунок 3.9. Выборка из двух таблиц с ограничением по дате
Обратите внимание на формат ограничения даты. Он не совпадает с форматом,
использовавшимся при заполнении таблицы.
При помощи локальных
инструкцию (Запрос10).
псевдонимов
можно
сократить
предыдущую
SELECT a.Продукт AS [Наименование
продукта], b.Количество AS [Количество]
FROM Продукты a, Продажи b
WHERE b.ДатаПродажи > #3/25/2003# AND a.КодПрод = b.КодПрод;
Вывод выбранных данных в определенном порядке
Для сортировки данных в инструкции SELECT имеются слова ORDER BY:
SELECT { * | [table.]field1 [AS alias1] [, [table.]
I, .-.]]}
field2 [AS alias2]
FROM table1 [table1Alias] [, table2 [table2Alias] [, ...]
[WHERE criteria]
[ORDER BY field1 [ASC I DESC ][, field2 [ASC | DESC ]][,
...]]]
Здесь к тем элементам SQL-запроса, которые уже рассмотрены, добавлено
необязательное предложение ORDER BY. Как следует из синтаксиса
инструкции SELECT, используя слова ASC и DESC, можно изменять
«направление» сортировки («по возрастанию» и «по убыванию»). Сортировать
можно по нескольким полям (сначала по одному, затем — по другому, и так
далее) и даже по различным элементам одного и того же поля с
использованием функций.
В следующей инструкции используется сортировка выводимого набора в
порядке убывания количества продаж (Запрос11):
SELECT a.Продукт AS [Наименование
продукта], b.Количество AS [Количество]
FROM Продукты a, Продажи b
WHERE b.ДатаПродажи > #3/25/2003# AND a.КодПрод = b.КодПрод
ORDER BY а. Продукт DESC;
Агрегирующие функции в инструкции SELECT
В инструкциях языка ANSI SQL предусмотрены так называемые агрегирующие
функции, которые определяют количество записей, вычисляют суммы всех
значений полей в наборе, находят минимальные или максимальные, а также
средние значения. К агрегирующим функциям относятся функции COUNT,
SUM, MAX, MIN и AVG.
Функция COUNT используется для определения количества записей в запросе.
Например, инструкция для вычисления количества записей в таблице
Продукты может быть записана следующим образом:
SELECT COUNT(Продукт) AS [Всего наименований]
FROM Продукты;
На рис. 3.10 показан результат выполнения этого запроса.
Рисунок 3.10. Подсчет количества продуктов
Функция AVG в инструкции SELECT позволяет найти среднее значение для
строк, входящих в запрос. Например, следующая инструкция определяет
среднюю цену продажи для сделок, совершенных после указанной даты
(Запрос13):
SELECT Format(AVG (ЦенаПродажи),
цена]
"### ##0.00р") AS [Средняя
FROM Продажи
WHERE ДатаПродажи > #3/25/2003#;
В конкретных реализациях SQL имеются другие агрегирующие функции,
которые следует использовать только в том случае, если вы уверены, что
никогда не захотите использовать фрагменты своего кода в различных СУБД.
Группировка данных в инструкции SELECT
Часто в наборах, получаемых при помощи SELECT-инструкций, встречаются
повторяющиеся значения. Для рассматриваемой нами базы данных это могут
быть, например, наименования продуктов в запросе (рис. 3.8). Такие
повторяющиеся значения можно объединять в группы, используя для групп
агрегирующие функции.
В инструкции SELECT для объединения значений в группы используется
предложение GROUP BY.
Следующая инструкция имеет результатом список проданных продуктов и их
суммарные количества (результат — на рис. 3.11):
SELECT a.Продукт AS [Наименование
продукта], SUM(b.Количество) AS [Количество]
FROM Продукты a, Продажи b
WHERE b.ДатаПродажи > #3/25/2003# AND a.КодПрод = b.КодПрод
GROUP BY a.Продукт;
Рисунок 3.11. Группировка объема продаж по наименованиям продуктов
Предположим, что нам нужна информация о суммарном количестве только тех
продуктов, для которых количество продаж меньше определенного числа.
Чтобы выполнить этот запрос, мы не можем использовать предложение
WHERE, так как оно «работает» со значениями данных, расположенными в
таблице, а нам нужно наложить некоторые ограничения на вычисляемые
данные.
Для
решения
подобной
задачи
следует
использовать
предложение HAVING, которое так же связано с предложением GROUP BY,
как WHERE сSELECT. Другими словами, предложение HAVING налагает
некоторые условия на выбранные посредством предложения GROUP BY
данные.
Следующая инструкция позволяет получить список продуктов и суммарное
количество продаж. Причем в список включаются только те продукты, для
которых суммарное количество продаж меньше чем 20 (результат — на рис.
3.12):
SELECT a.Продукт AS [Наименование
продукта], SUM(b.Количество) AS [Количество]
FROM Продукты a, Продажи b
WHERE b.ДатаПродажи > #3/25/2003# AND a.КодПрод = b.КодПрод
GROUP BY a.Продукт
HAVING SUM(b.Количество) < 20;
Рисунок 3.12. Группировка продаж, не превышающих заданной величины
Подзапросы в инструкции SELECT
Подзапрос — это запрос, который размещается внутри другого запроса, а
точнее, является частью предложения WHERE (или HAVING) основного
запроса и заключается в круглые скобки. Иногда подзапросы называют
вложенными запросами. Запрос, содержащий подзапрос, называют сложным
запросом. При выполнении сложного запроса сначала выполняется подзапрос
(он для этого и заключается в скобки!), а затем — основной запрос.
Выходные данные подзапроса обычно используются при оценке выражения в
предложении WHERE (или HAVING) основного (по отношению к данному
подзапросу) запроса с использованием таких операторов, как =, >, <, о, IN, NOT
IN, AND, OR. (Эти операторы можно использовать и внутри подзапроса.)
Очень важно понимать, какие данные возвращает подзапрос, поскольку от
этого зависит синтаксис использования предложения WHERE. Необходимо при
написании сложных запросов соблюдать следующие правила:

Предложение SELECT подзапроса обычно содержит только один столбец
и, следовательно, может иметь результатом массив однородных (только
строковые значения, только целые значения и т.д.) значений или только
одно значение. Очень редко встречаются случаи использования нескольких
столбцов. Если подзапрос возвращает массив значений, соответствующее
этому подзапросу предложение WHERE может содержать только
многозначные операторы, например, IN.

Предложение ORDER BY следует использовать только в основном
запросе. В подзапросе для упорядочения данных необходимо применять
предложение GROUP BY.

Недопустимо использование в основном запросе предложения BETWEEN
Простой синтаксис подзапроса для оператора SELECT следующий:
SELECT { * I table.* | [table.]field1 [AS allas1] [, [table.]field2 [AS
alias2] [, ...]])
FROM table1 [table1Alias] [, table2 [table2Alias] [, ...]
WHERE field1 operator
(SELECT { * I table.* I [table.]field1 [AS alias1] [, [table.]field2 [AS
alias2] [, ...]]}
FROM table1 [table1Alias] [, table2 [table2Alias] [, ...]
WHERE [criteria])
Проще всего продемонстрировать использование подзапроса, если он имеет
результатом единственное значение. Например, пусть нам необходимо
получить список продуктов от поставщика, поставки которого наиболее
разнообразны (поставляет наибольшее количество наименований).
Напомним, что схема данных (рис. 3.13) БД Lab 3.mdb та же, что и в Lab 2.mdb.
Рисунок 3.13. Схема данных Lab 3.mdb
Запрос, связывающий
следующим образом:
продажи
продуктов
с
поставщиками
выглядит
SELECT a.Продукт AS [Наименование
продукта], b.Количество AS [Количество], d.КодПост AS [Поставщик
]
FROM Продукты a, Продажи b, Поставки c, Поставщики d
WHERE a.КодПрод = b.КодПрод AND b.КодПрод = c.КодПрод AND c.К
одПост = d.КодПост;
Его результат показан на рис. 3.14.
Рисунок 3.14. Продажи, связанные с поставщиками
Для начала нам нужно определить этого поставщика, предоставившего
наибольшее количество наименований товара. Создадим запрос, который
возвратит код такого поставщика:
SELECT ТОР 1 КодПост
FROM Поставки
GROUP BY КодПост
ORDER BY COUNT(КодПрод) DESC
Предложение TOP 1 указывает на то, что в результирующий набор попадает
только одна запись, а поскольку набор сортируется (по убыванию) по
суммарным количествам продуктов, то в результате мы получаем код
поставщика с наибольшим количеством наименований. Результат такого
запроса показан на рис. 3.15.
Рисунок 3.15. Код поставщика с наибольшим количеством наименований
Остается подготвить запрос, который возвращает список проданных продуктов
для указанного кода поставщика, но если ранее мы бы указывали этот код явно,
то теперь определяем его в подзапросе (результат — на рис. 3.16):
SELECT a.Продукт AS [Наименование
продукта], b.Количество AS Количество, d.КодПост AS Поставщик
FROM Продукты AS a,
Поставщики AS d
Продажи AS b,
Поставки AS c,
WHERE a.КодПрод = b.КодПрод AND b.КодПрод = c.КодПрод AN
D c.КодПост = d.КодПост AND c.КодПост =
(SELECT TOP 1 КодПост
FROM Поставки
GROUP BY КодПост
ORDER BY COUNT(КодПрод) DESC);
Рисунок 3.16. Продажи продуктов от поставщика с наибольшим количеством наименований
Анализ такого запроса показывает, что количество проданных наименований
существенно меньше количества наименований продуктов, предоставленных
данным поставщиком.
Заменив в первой строке запроса d.КодПост на d. Поставщик получим
результат официальным названием фирмы (рис. 3.17).
Рисунок 3.17. Название фирмы в явном виде
Скачать