Диго С.М. Базы данных проектирование и использование (1084447), страница 47
Текст из файла (страница 47)
SELECT а_сотрудники.таб_ном, а_сотрудники.фио, б_разработки.
фио, б_разработки.продукт
FROM а_сотрудники, б_разработки;
Чаще всего при создании запросов используется тип соединения INNER JOIN, при котором соединенная таблица будет включать только те строки, для которых есть соответствующие друг другу значения полей связи в обеих таблицах.
Результат соединения типа INNER JOIN для приведенных выше таблиц представлен ниже.
Таб_ном | ФИО | Продукт |
01 | Диго | П2 |
01 | Диго | П1 |
02 | Афанасьев | ПЗ |
Этот запрос показывает разработки, выполненные сотрудниками фирмы X.
На SQL такой запрос будет иметь следующий вид:
SELECT а_сотрудники.таб_ном, а_сотрудники.фио, б_разработки.продукт
FROM а_сотрудники INNER JOIN б_разработки
ON а_сотрудники.фио = б_разработки.фио;
При использовании соединения типа LEFT JOIN в результатную таблицу попадают все записи из первой таблицы и только те записи из второй таблицы, для которых есть соответствующие значения полей связи в первой таблице. Соединение типа LEFT JOIN для рассматриваемого примера даст в результате список всех сотрудников фирмы X с указанием их разработок:
Таб_ном | ФИО | Продукт |
01 | Диго | П2 |
01 | Диго | Ш |
02 | Афанасьев | ПЗ |
03 | Сидоров | Null |
На SQL такой запрос будет выглядеть следующим образом:
SELECT а_сотрудники.таб_ном, а_сотрудники.фио, б_разработки.продукт
FROM а_сотрудники LEFT JOIN б_разработки
ON а_сотрудники.фио = б_разработки.фио;
При использовании соединения типа RIGHT JOIN, напротив, в результатную таблицу попадают все записи из второй таблицы и только те записи из первой таблицы, для которых есть соответствующие значения полей связи во второй таблице. Соединение типа LEFT JOIN для рассматриваемого примера даст в результате список всех продуктов с указанием разработчика и его табельного номера:
Таб_ном | ФИО | Продукт |
01 | Диго | Ш |
01 | Диго | П2 |
02 | Афанасьев | ПЗ |
Чистов | П4 |
На SQL такой запрос будет выглядеть следующим образом:
SELECT а_сотрудники.таб_ном, б_разработки.фио, б_разработки.продукт
FROM а_сотрудники RIGHT JOIN б_разработки
ON а_сотрудники.фио = б_разработки.фио;
Во всех приведенных выше примерах предполагалось, что условием соединения является равенство значений полей связи. Обычно именно этот тип сравнения и используется.
Как уже указывалось, все возможности стандартного SQL в полном объеме практически не реализованы ни в одной СУБД. Операторы INNER, LEFT, RIGHT JOIN присутствуют во многих системах, чего нельзя сказать о FULL и UNION JOIN.
FULL JOIN для нашего примера даст следующий результат:
Таб_ном | ФИО | Продукт |
01 | Диго | П1 |
01 | Диго | П2 |
02 | Афанасьев | ПЗ |
03 | Сидоров | Null |
Null | Чистов | П4 |
Результатом UNION JOIN будет
Таб_ном | ФИО | Продукт |
03 | Сидоров | Null |
Null | Чистов | П4 |
Предложение WHERE. В нем задается условие отбора записей. Предикат может включать одно выражение или несколько. Части сложного условия соединяются логическими операторами AND (И) или OR (ИЛИ).
В выражениях могут использоваться следующие операторы сравнения: = (равно), о (не равно), < (меньше), <= (меньше или равно), > (больше), >= (больше или равно), которые могут предваряться оператором NOT.
Предикат может принимать одно из трех значений: TRUE, FALSE, UNKNOWN. В результатную таблицу переносятся те строки, для которых значение предиката равно TRUE.
Кроме стандартных операторов сравнения в SQL можно использовать специальные операторы предикатов:
-
<интервальный предикат >;
-
<предикат Ш>;
-
< предикат проверки на неопределенное значение >;
-
<предикат подобия>.
При использовании интервального предиката диапазон значений можно задавать в виде
WHERE [NОТ]<выражение> BETWEEN <нижнее выражение> AND <верхнее выражение>.
Например, если требуется выдать сведения о поставке продукции за последнюю декаду ноября 2002 г., то запрос можно задать следующим образом:
SELECT * FROM post WHERE postdate BETWEEN #11/20/02# AND #11/30/02#;
Это же условие отбора можно задать и без использования интервального предиката:
postdate>=#11/20/02# AND postdate<= #11/30/02#;
При использовании предиката IN предложение WHERE будет иметь следующий вид:
WHERE [NOT]< выражение > [NOT] IN (<список значений>/<лод-запрос>).
В приведенном ниже примере требуется вывести данные о поставках поставщиков PI, P2, РЗ.
SELECT * FROM post WHERE kod_post IN ("p1", "p2", "p3")
Без использования IN запрос имел бы следующий вид:
SELECT * FROM post WHERE kod_post ="p1" OR kod_post ="p2" OR kod_post = "p3";
Пример с использованием подзапроса будет рассмотрен позже, при демонстрации возможностей обработки нескольких таблиц.
Предикат подобия применяется для поиска подстроки в указанной строке. Предложение WHERE при использовании предиката этого типа будет иметь следующий вид:
WHERE [NOT] <выражение_для_вычисления_значения_строки_1>
[NOT] LIKE <выражение_для_вычисления_значения_строки_2>.
В качестве <выражения_для_вычисления_значения_строки_1> обычно используется <имя колонки>.
<Выражение_для_вычисления_значения_строки_2> называется образцом. В образце разрешается применять заполнители (трафаретные символы):
-
символ подчеркивания (_) - используется вместо любого единичного символа в проверяемом значении;
-
символ процента (%) - заменяет набор любых символов в проверяемом значении.
Предположим, что коды металлов начинаются с буквы «м». Тогда запрос, позволяющий вывести сведения о поставке металлов, будет иметь вид
SELECT * FROM post WHERE kod_mat LIKE "м%";
Предикат проверки на неопределенное значение имеет вид
предикат NULL ::=
конструктор значения строки IS [NOT] NULL
Например, если в таблице «Сотрудник» (sotr) есть поле «Ученая_степень» (ych_st), то запрос, выводящий список сотрудников, не имеющих ученых степеней, будет выглядеть следующим образом:
SELECT fio FROM sotr WHERE ych_st IS NULL;
При использовании подзапросов в условии WHERE может быть использован квантор существования EXISTS. Формат условия WHERE в этом случае имеет вид
WHERE [NOT] EXISTS
(<подзапрос>).
EXISTS проверяет, вернул ли подзапрос какие-либо ряды. Фактически любой подзапрос, который может быть выражен с использованием IN, может альтернативным образом быть сформулирован также с использованием EXISTS. Обратное утверждение несправедливо.
Пример запроса с использованием EXISTS:
SELECT naimmat
FROM cennik
WHERE EXISTS
(SELECT *
FROM post
WHERE kodpost='P01' AND
cennik.kodmat=post.kodmat);
Предложение GROUP BY. Оно используется для определения групп выходных строк, к которым могут применяться те или иные агрегатные функции. Предложение GROUP BY всегда используется со встроенными агрегатными функциями. Обратное утверждение неверно. Агрегатные функции могут использоваться в предложениях SELECT, HAVING. Если агрегатные функции используются без предложения GROUP BY, то они будут применяться ко всему набору строк, удовлетворяющему условию запроса.
Конструкция GROUP BY работает только на одном уровне. Нельзя разбить каждую из этих групп на группы более низкого уровня, а затем применять стандартную функцию на каждом уровне подчиненности.
Например, в таблице «Zarpl», содержащей сведения о заработной плате рабочих, имеются колонки FIO (фамилия, инициалы), «ТаЬпош» (табельный номер), «Uch» (участок), «Zpl» (заработная плата). Требуется определить среднюю заработную плату по каждому участку:
SELECT uch, AVG(zpI)
FROM zarple
GROUP BY uch;
В данном примере рассматривается группировка по одной колонке. В принципе можно группировать строки таблицы по любой комбинации ее колонок. В этом случае имена колонок в предложении GROUP BY перечисляются через запятую.
Фраза GROUP BY означает логическую перекомпоновку (группировку) таблицы по указанной колонке (колонкам). Физически таблицы в базе данных не перекомпоновываются. Логика выполнения запроса при использовании GROUP BY несколько отличается от реализации обычного запроса. Фраза SELECT при использовании GROUP BY применяется к каждой группе, а не к каждой строке, как обычно.
Каждое выражение во фразе SELECT должно принимать единственное значение для группы, т.е. оно может быть либо самой колонкой, либо арифметическим выражением, включающим эту колонку, либо агрегатной функцией, которая получает в результате единственное значение для группы. Кроме того, в SELECT может быть включена константа.
Предложение HAVING. Вместе с GROUP BY может использоваться фраза HAVING, которая для групп имеет то же значение, что и фраза WHERE - для строк.
Например, запрос на выдачу списка кодов тех материалов, по которым было выполнено более чем по одной поставке, будет выглядеть следующим образом:
SELECT codmat
FROM post
GROOUP BY codmat
HAVING COUNT(*)>1;
Выражение во фразе HAVING должно принимать единственное значение для группы. Формат COUNT(*) означает подсчет всех строк таблицы.
Предложение ORDER BY. Информация, получаемая в результате реализации запроса, может быть упорядочена. Для этого используется фраза ORDER BY. Строки сортируются в соответствии со значениями столбцов, указанных в списке. В этом списке могут задаваться либо имена колонок, либо целое число, которое соответствует номеру колонки в таблице, считая слева направо. Когда колонки, по которым осуществляется упорядочение, вычисляемые или являются результатом операции UNION, то «целое» должно использоваться вместо имени колонки.
Параметр ASC/DESC означает вид сортировки (по возрастанию /по убыванию соответственно). По умолчанию принимается значение ASC.
Если в ORDER BY специфицируется список полей, то это означает упорядочение по составному ключу. Старшинство полей сортировки будет определяться порядком следования полей в списке.