- •1.1. Технические параметры баз данных
- •1.2. Организация субд
- •1.6. Сетевая и иерархическая модели данных
- •1.7. Case - методы проектирования баз данных
- •1.8. Понятия “сущность” и “взаимосвязь”
- •4. Складывание.
- •5.3. Индексированные файлы
- •5.4. Операции с поиском по неключевым полям
- •6.2. Типы данных в sql
- •Int Число без десятичной точки. Эквивалентно decimal, но без
- •6.3. Обозначения в командах sql
- •6.... Оператор in
- •6.... Оператор between
- •6.... Оператор like
- •6.... Оператор is null
- •7.5... Скалярное выражение на основе выбранных полей
- •7.6... Упорядочение вывода полей
- •7.7.. Объединения нескольких таблиц в запросе
- •7.8.. Создание обьединения
- •7.9..Объединение таблиц через справочную целостность
- •7.10.. Объединения таблиц по равенству значений
- •7.11.. Объединение более двух таблиц
- •7.12. Объединение таблицы с собой
- •8.2. Значения, которые могут выдавать подзапросы
- •8.3. Предикаты с подзапросами являются необратимыми
- •8.4. Использование агрегатных функций в подзапросах
- •8.5. Использование подзапросов которые выдают
- •8.8. Подзапросы в предложении having
- •Insert into Londonstaff
- •Insert into Daytotals (date, total)
- •Insert для этой таблицы. Null - это наиболее широко используемое
- •1009, И Hoffman и Clemens будут также автоматически изменены.
- •Insert Пользователь с этой привилегией может выполнять
- •Insauth Имеет ли пользователь привилегию insert
- •Values ( :id_num, :salesperson, :loc, :comm)
- •Values (:id_num, :salesperson, :loc, :comm);
- •Into :id_num, :salesperson, :loc, :comm
- •Into :salesnum
- •1. Команда выполнилась без ошибки, но не произвела никакого
- •Into :id_num, :salesperson, :loc, :comm;
- •Indicator.
- •Indicator, связывая ее с каждой переменной главного языка, специальным способом, эмулирующим поведение null значений sql.
- •Values (:Id_num, :salesperson, :loc:i_a, :comm:i_b);
- •Indicator. Переменные indicator следуют за другим именами переменных в команде sql, без каких бы то ни было посторонних символов
8.4. Использование агрегатных функций в подзапросах
Один тип функций, который автоматически может производить одиночное значение для любого числа строк, конечно же, - агрегатная функция.
Любой запрос использующий одиночную функцию агрегата без предложения GROUP BY будет выбирать одиночное значение для использования в основном предикате. Например, вы хотите увидеть все приобретения, имеющие сумму выше средней на 4-е Октября:
SELECT *
FROM Orders
WHERE amt > ( SELECT AVG (amt) FROM Orders
WHERE odate = 10/04/1990 );
=============== SQL Execution Log ==============
| onum amt odate cnum snum |
| ----- -------- ---------- ----- ----- |
| 3002 1900.10 10/03/1990 2007 1004 |
| 3005 2345.45 10/03/1990 2003 1002 |
| 3006 1098.19 10/03/1990 2008 1007 |
| 3009 1713.23 10/04/1990 2002 1003 |
| 3008 4723.00 10/05/1990 2006 1001 |
| 3010 1309.95 10/06/1990 2004 1002 |
| 3011 9891.88 10/06/1990 2006 1001 |
================================================
Средняя сумма приобретений на 4 Октября, равная 1788.98=1713.23 + 75.75, равняется 894.49. Все строки со значением в поле amt выше этого являются выбраными.
Имейте ввиду, что сгруппированные агрегатные функции, которые являются агрегатными функциями, определенными в терминах предложения GROUP BY, могут производить многочисленые значения. Они, следовательно, не позволительны в подзапросах такого характера. Даже если GROUP BY и HAVING используются таким способом, что только одна группа выводится с помощью подзапроса, команда будет отклонена в принципе. Вы должны использовать одиночную агрегатную функцию с предложением WHERE, что устранит нежелательные группы.
Например, следующий запрос, который должен найти среднее значение комиссионных продавца в Лондоне -
SELECT AVG (comm)
FROM Salespeople
GROUP BY city HAVlNG city = “London”;
не может использоваться в подзапросе! Во всяком случае это не лучший способ формировать запрос. Другим способом может быть -
SELECT AVG (comm)
FROM Salespeople
WHERE city = “London”;
8.5. Использование подзапросов которые выдают
МНОГО СТРОК С ПОМОЩЬЮ ОПЕРАТОРА IN
Вы можете использовать подзапросы, которые производят любое число строк, если вы используете специальный оператор IN ( операторы BETWEEN, LIKE, и IS NULL не могут использоваться с подзапросами ). Как вы помните, IN определяет набор значений, одно из которых должно совпадать с другим термом уравнения предиката, чтобы предикат был истинным.
Когда вы используете IN с подзапросом, SQL просто формирует этот набор из вывода подзапроса. Мы можем, следовательно, использовать IN, чтобы выполнить такой же подзапрос, который не будет работать с реляционным оператором, и найти все атрибуты таблицы Приобретений для продавца в Лондоне:
SELECT *
FROM Orders
WHERE snum IN
( SELECT snum
FROM Salespeople
WHERE city = “LONDON” );
====== SQL Execution Log ==============
| onum amt odate cnum snum |
| ----- -------- ---------- ----- ------ |
| 3003 767.19 10/03/1990 2001 1001 |
| 3002 1900.10 10/03/1990 2007 1004 |
| 3006 1098.19 10/03/1990 2008 1007 |
| 3008 4723.00 10/05/1990 2006 1001 |
| 3011 9891.88 10/06/1990 2006 1001 |
=====================================
В ситуации, подобно этой, подзапрос более прост для пользователя, чтобы понимать его и более прост для компьютера, чтобы его выполнить, чем если бы Вы использовали обьединение:
SELECT onum, amt, odate, cnum, Orders.snum
FROM Orders, Salespeople
WHERE Orders.snum = Salespeople.snum
AND Salespeople.city = “London”;
Хотя это и произведет тот же самый вывод что и в примере с подзапросом, SQL должен будет просмотреть каждую возможную комбинацию строк из двух таблиц и проверить их снова по составному предикату.
Проще и эффективнее извлекать из таблицы Salespeople значения поля snum, где city = “London”, и затем искать эти значения в таблице Приобретений, как это делается в варианте с подзапросом. Внутренний запрос дает нам snums=1001 и snum=1004. Внешний запрос, затем, дает нам строки из таблицы Приобретений, где эти поля snum найдены.
Строго говоря, быстрее или нет работает вариант подзапроса, практически зависит от реализации - в какой программе вы это используете.
Конечно, вы можете также использовать оператор IN, даже когда вы уверены, что подзапрос произведет одиночное значение. В любой ситуации, где вы можете использовать реляционный оператор сравнения (=), вы можете использовать IN. В отличие от реляционных операторов, IN не может заставить команду потерпеть неудачу, если больше чем одно значение выбрано подзапросом. Это может быть или преимуществом или недостатком.
В принципе, если вы знаете что подзапрос должен( по логике) вывести
только одно значение, вы должны использовать = .
IN является подходящим, если запрос может ограниченно производить одно или более значений, независимо от того, ожидаете вы их или нет.
8.6. ПОДЗАПРОСЫ ВЫБИРАЮТ ОДИНОЧНЫЕ СТОЛБЦЫ
Смысл всех подзапросов обсужденных в этой главе тот, что все они выбирают одиночный столбец. Это обязательно, поскольку выбранный вывод сравнивается с одиночным значением. Подтверждением этому то, что SELECT * не может использоваться в подзапросе. Имеется исключение из этого, когда подзапросы используются с оператором EXISTS.
8.7. ИСПОЛЬЗОВАНИЕ ВЫРАЖЕНИЙ В ПОДЗАПРОСАХ
Вы можете использовать выражение, основанное на столбце, а не просто сам столбец, в предложении SELECT подзапроса. Это может быть выполнено или с помощью реляционных операторов или с IN. Например, следующий запрос использует реляционный оператор = :
SELECT *
FROM Customers
WHERE cnum =
( SELECT snum + 1000
FROM Salespeople
WHERE sname = ‘Serres’ );
Он находит всех заказчиков, для которых значение поля cnum на 1000 больше поля snum Serres. Мы предполагаем, что столбец sname не имеет никаких двойных значений ( это может быть предписано или UNIQUE INDEX, обсуждаемым позже, или ограничением UNIQUE; иначе
=============== SQL Execution Log ============
| |
| SELECT * |
| FROM Customers |
| WHERE cnum = |
| (SELECT snum + 1000 |
| WHERE Salespeople |
| WHERE sname = ‘Serres’ |
| ============================================= |
| cnum cname city rating snum |
| ----- -------- ---- ------ ----- |
| 2002 Giovanni Rome 200 1003 |
=============================================
подзапрос может произвести многочисленые значения. Когда поля snum и сnum не имеют такого простого функционального значения, как например, первичный ключ , что не всегда хорошо, запрос типа вышеупомянутого невероятно полезен.