- •1.1. Архитектура хост/терминал
- •1.2. Архитектура файл/серввр
- •2.1 Сетевая модель данных
- •2.2. Реляционная модель данных
- •4.2. Первичные ключи. Что выбрать в качестве первичных ключей для каждой из таблиц?
- •4.3. Нормализация данных
- •4.4. Типы данных
- •5.1. Предназначение IDEF1X
- •5.2. Сущности в IDEF1X и их атрибуты
- •5.3. Связи между сущностями
- •5.4. Идентификация сущностей. Представление о ключах
- •5.5.Классификация сущностей в IDEF1X. Зависимые и независимые сущности
- •5.7. Преимущества IDEF1X
- •6.2. Оператор SELECT
- •6.3. Работа с несколькими таблицами
- •6.5. Объединение множества запросов в один
- •6.6.Команды модификации данных
- •6.7. Модификация структуры данных
- •ИНФОРМАЦИОННОЕ ОБЕСПЕЧЕНИЕ СИСТЕМ УПРАВЛЕНИЯ
цов указываются без агрегатных функций, то есть по этим полям произво дится группировка.
6.2.8. Условия поиска групп HAVING. Точно так же, как предложение WHERE, используется для отбора отдельных строк, участвующих в запро се, предложение HAVING можно применить для отбора групп строк. Его формат соответствует формату предложения WHERE. Предложение HAV ING состоит из ключевого слова HAVING, за которым следует условие поиска. Таким образом, данное предложение определяет условие поиска для групп. Основным отличием предложения HAVING от WHERE в том, что оно применяется уже непосредственно после самого запроса и в усло вие поиска включается поле с примененной к нему агрегатной функцией.
Вывести те дни месяца, когда оборот превышал 1000 руб. :
SELECT ДАТА_ДОК, SUM (КОЛ-ВО*ЦЕНА) SUM (КОЛ-ВО*ЦЕНА)
FROM ПЕРЕМЕЩЕНИЕ
WHERE ДАТА_ДОК BETWEEN ‘1.01.2000’ AND ’31.01.2000’ GROUP BY ДАТА_ДОК
HAVING SUM (КОЛ-ВО*ЦЕНА)> 1000
Вывести все идентификаторы городов, если количество клиентов из них больше трех:
SELECT IDN_ГОРОДА FROM КЛИЕНТ
GROUP BY IDN_TOPOM HAVING COUNT(*) >3
6.3. Работа с несколькими таблицами
6.3.1. Объединение при помощи оператора WHERE. На практике мно гие запросы считывают данные сразу из нескольких таблиц базы данных. Например, у нас существуют две таблицы:
Таблица Города
IDN |
НАЗВАНИЕ |
100 |
Москва |
102Санкт-Петербург
103Пермь
105 Париж
IDN |
НАЗВАНИЕ(ИМЯ) |
IDN ГОРОДА |
1 |
МММ |
100 |
2 |
Хопер |
100 |
3 |
Алиса |
102 |
4 |
иве |
103 |
5 |
ПГТУ |
103 |
6 |
Рога&Копыта |
|
Вывести всех клиентов с указанием города:
SELECT ГОРОДА.НАЗВАНИЕ, КЛИЕНТ.НАЗВАНИЕ(ИМЯ) FROM ГОРОДА,КЛИЕНТ
WHERE ГОРОДА.IDN=KЛИЕНТ.ШМ_ГОРОДА
Результат этого запроса:
Москва |
МММ |
Москва |
Хопер |
Санкт- |
Алиса |
Петербург |
|
Пермь |
и в е |
Пермь |
ПГТУ |
Если бы нам нужны были клиенты только из Москвы, то этот запрос до полнился бы еще одной строкой:
AND ГОРОДА-НАЗВАНИЕ =’Москва’
В качестве упрощенного варианта этот же запрос можно записать сле дующим образом:
SELECT Г.НАЗВАНИЕ, К.НАЗВАНИЕ(ИМЯ) FROM ГОРОДА Г., КЛИЕНТ К.
WHERE r.IDN=K.IDN_rOPOM AND Г.НАЗВАНИЕ=’Москва’
Нас интересует, на какую сумму был оборот по каждой группе товаров за какой-то промежуток времени:
SELECT ГР.НАЗВАНИЕ, 8ЦМ(П.КОЛ-ВО*П.ЦЕНА) FROM ГРУППЫ ГР., ПЕРЕМЕЩЕНИЕ П.
WHERE rP.IDN=n.IDN_rpyimbI AND П.ДАТА_ДОК
BETWEEN ‘1.02.2000’ AND ’16.03.2000’
GROUP BY ГР.НАЗВАНИЕ
HAVING 8ЦМ(П.КОЛ-ВО*П.ЦЕНА)> 1000 ORDER BY 8иМ(П.КОЛ-ВО*П.ЦЕНА)
6.3.2.Внутренние и внешние объединения. Примеры, рассмотренные
впредыдущем разделе, формально относятся к так называемым внутрен ним объединениям. Внутреннее объединение возвращает строки, только если условие объединения выполнено. Приведем еще раз пример запроса с использованием оператора JOIN (соединять).
Вывести всех клиентов с указанием города:
SELECT ГОРОДА-НАЗВАНИЕ, КЛИЕНТ.НАЗВАНИЕ(ИМЯ) FROM ГОРОДА
INNER JOIN КЛИЕНТ ON ГОРОДАЛО^КЛИЕНТЛО^ГОРОДА
Результат этого запроса:
Москва |
МММ |
Москва |
Хопер |
Санкт-Петербург |
Алиса |
Пермь |
иве |
Пермь |
ПГТУ |
Обратите внимание, что ни город Париж, ни клиент Рога&Копыта в результаты запроса не попали.
На то, что мы имеем дело с внутренним объединением, указывает ключевое слово INNER (внутренний). Помимо внутренних объединений часто имеет смысл использовать внешние объединения, которые возвра щают строки независимо от того, выполнено условие объединения или нет. Когда условие объединения не выполнено для данной строки во внешнем объединении, поля из внутренней таблицы возвращаются, как
NULL.
Различают правые и левые внешние объединения, которые различа ются тем, из какой таблицы (внутренней или внешней) извлекаются все строки. Приведем примеры.
Левое внешнее объединение.
Вывести всех клиентов, если для клиента указан город, показать его:
SELECT ГОРОДА.НАЗВАНИЕ, KJMEHT.HA3BAHHE(HMiI)
FROM ГОРОДА
LEFT OUTER JOIN КЛИЕНТ ON ГОРОДА.Ш^КЛИЕНТ.ГО^ГОРОДА
Результат этого запроса:
Москва |
МММ |
Москва |
Хопер |
Санкт-Петербург |
Алиса |
Пермь |
иве |
Пермь |
ПГТУ |
|
Рога&Копыта |
Обратите внимание, что был выведен клиент Рога&Копыта, для кото рого город не указан.
В этом запросе были использованы ключевые слова LEFT (левый) OUTER (внешний).
Правое внешнее объединение.
Вывести все города и всех клиентов из этих городов:
SELECT ГОРОДА.НАЗВАНИЕ, КЛИЕНТ.НАЗВАНИЕ(ИМЯ) FROM ГОРОДА
RIGHT OUTER JOIN КЛИЕНТ ON rOPO/(A.IDN=KJIHEHT.IDN_rOPO<aA
Результат этого запроса:
Москва |
МММ |
Москва |
Хопер |
Санкт-Петербург |
Алиса |
Пермь |
иве |
Пермь |
ПГТУ |
Париж |
|
Врезультате теперь присутствует Париж.
6.4.Вложенные запросы
6.4.1. Исходная база данных. Эта база данных далее будет использо ваться в примерах.
Таблица Клиент
IDN IDN ГОРОДА имя |
РЕКВИЗИТ IDN БАНКА |
|||
204 |
101 |
Петров |
— |
311 |
205 |
104 |
Кузнецов |
|
314 |
206 |
102 |
Иванов |
|
317 |
208 |
104 |
Золин |
|
311 |
210 |
105 |
Киров |
|
323 |
212 |
103 |
Павлов |
|
317 |
215 |
105 |
| Петренко |
|
318 |
Таблица Города
IDN НАЗВАНИЕ
102Минск
101Москва
103Саратов 104 Пермь 105 Киев
IDN РЕКВИЗИТЫ 311 МММ
314 Альфабанк
317Сбербанк
323Менатеп
318Западуралбанк
Таблица Перемещение
IDN ПОРЯД
КОВ №
о О
Д А Т А . |
НО |
IDN |
IDN |
к о л - |
ЦЕ |
ДОК |
МЕР |
ГРУП |
МАТ. |
в о |
НА |
|
д о к |
ПЫ |
ЦЕН. |
|
|
|
|
402 |
501 |
|
20 |
|
|
402 |
503 |
|
25 |
|
|
404 |
505 |
|
6 |
|
|
404 |
504 |
|
7 |
|
|
404 |
506 |
|
5 |
|
|
406 |
508 |
|
15 |
|
|
406 |
507 |
|
25 |
Некоторые столбцы не заполнены, т.к. не используются в примерах.
Таблица Группы
IDN НАЗВАНИЕ 402 Газ. вода 404 Шоколад 406 Сигареты
Таблица Мат. ценности |
|
|
IDN ГРУППЫ |
IDN МАТ.ЦЕН. |
IDN МАТ.ЦЕН. |
402 |
501 |
Fanta |
402 |
503 |
Sprite |
404 |
505 |
Mars |
404 |
504 |
Twix |
404 |
506 |
Шок |
406 |
508 |
Кама |
406 |
507 |
L&M |
6.4.2. Вложение запросов. SQL позволяет вкладывать запросы друг в друга. Внешний запрос использует значения, которые генерируются во внутреннем запросе. Предположим, необходимо извлечь всю информа цию о банке, с которым работает Киров. Вот один из способов решения:
SELECT * FROM БАНКИ
WHERE IDN =(SELECT IDN_EAHKA FROM КЛИЕНТ WHERE ИМЯ=‘Киров’)
Выходные данные: IDN РЕКВИЗИТ 323 Менатеп
Чтобы оценить основной запрос, SQL должен оценить внутренний запрос (или подзапрос) в предложении WHERE Подзапрос оценивается так, как если бы он был основным запросом: просматриваются все стро ки таблицы Клиент и выбираются те строки, для которых значение поля Имя равно Киров, для таких строк выбираются значения поля IDNJSAHKA.
В результате выбранной оказывается строка с IDN_BAHKA = 323. SQL подставляет его в предикат основного запроса вместо подзапроса, теперь предикат читается следующим образом:
WHERE IDN =323
После этого основной запрос выполняется как обычный, его результат показан выше.
Если указать просто:
WHERE IDN =323
можно освободиться от подзапроса, но использование подзапроса делает процедуру более гибкой .
В следующем примере использование подзапроса обязательно.
Получить все банки, которые не используются клиентами:
SELECT * FROM Банки
WHERE (SELECT COUNT(*) FROM Клиент WHERE Клиент.ГОИ_банка = Банки-IDN) = О
\Подзапрос возвращает количество клиентов для каждого ЮЫ_банка из внешнего запроса. Внешний запрос выдает только те банки, для которых это количество равно нулю._______________________________
Еще один пример, когда необходимо использовать подзапрос:
Для каждой группы товаров найти товар с минимальной ценой, вывести название группы, название товара, цену:
SELECT Г.НАЗВАНИЕ, M НАЗВАНИЕ, П.ЦЕНА
FROM Группы Г, МАТ.ЦЕННОСТИ М, ПЕРЕМЕЩЕНИЕ П WHERE M.IDN ГРУППЫ = n.IDN ГРУППЫ
AND M.IDN МАТ.ЦЕН. = n.IDN |
МАТ.ПЖ |
|
AND r.IDN = n.ID N ГРУППЫ |
j Эти три |
подчеркнутых равенства |
|
связывают |
таблицы между собой, |
AND П.ИЕНА = fSELECT MIN ШЕНА) |
т.к. надо получить в результате на |
FROM Перемещение ПВНУТР |
звание, а в таблице Перемещение |
WHERE n.ID N ГРУППЫ = |
хранятся только идентификаторы. |
|
|
ПВНУТР.ПЖ ГРУППЫ) ч |
|
'Это равенство связывает цену из внешнего запроса с минимальной ценой для каждой группы, найденной в подзапросе.
6.4.3.Оператор EXISTS. EXISTS (существует ) - оператор, генери рующий значения «истина» или «ложь». Его можно применять отдельно в предикате или комбинировать с другими выражениями с помощью опера торов AND, OR, NOT. Этот оператор оценивает подзапрос как истинный, если подзапрос генерирует выходные данные, а в противном случае - как ложный, иными словами, оператор EXISTS возвращает значение «истина», если подзапрос возвращает хотя бы одну строку. В отличие от прочих операторов и предикатов, он не может принимать значения unknown (не известный). Например, нужно извлечь данные из таблицы Клиент в том случае, если один (или более) клиент из нее работает с банком МММ:
SELECT * FROM КЛИЕНТ , WHERE EXISTS
(SELECT* FROM КЛИЕНТ WHERE НЖ_банка = 311)
Выходные данные: |
|
|
|
IDN |
IDN ГОРОД] ИМЯ |
РЕКВИЗИТЫ IDN БАНКА |
|
204 |
101 |
Петров |
311 |
205 |
104 |
Кузнецов |
314 |
206 |
102 |
Иванов |
317 |
208 |
104 |
Золин |
311 |
210 |
105 |
Киров |
323 |
212 |
103 |
Павлов |
317 |
215 |
105 |
Петренко |
318 |
Внутренний запрос выбрал все данные обо всех клиентах, работаю щих с МММ. Т.к. такие клиенты существуют, оператор EXISTS отметил, что подзапрос генерирует выходные данные и принимает значение «исти на». В данном случае тот же результат можно было получить проще, одна ко бывают случаи, когда без EXISTS не обойтись: