Тарифы Услуги Сим-карты

Вложенные и связанные подзапросы в SQL, предикат EXISTS. Вложенные запросы. Примеры

  • 4.Основные понятия в концептуальном проектировании реляционных баз данных (сущность, атрибуты, отношения). Элементы реляционной модели.
  • Зависимости между атрибутами
  • 5.Целостность данных и ее виды. Нарушения целостности (аномалии).
  • 6.Функциональные связи атрибутов и нормализация таблиц. Основные нормальные формы (нф). Примеры нф.
  • 7.Использование er–моделирования в концептуальном проектировании бд. Диаграммы er- экземпляров и er-типов.
  • 8.Преобразование концептуальной модели в реляционную. Основные этапы и правила формирования отношений (пример).
  • 9.Структура и основные технические характеристики субд access 200*.Возможности проектирования персональных и сетевых приложений.
  • 10.Конструирование таблиц в ms access хр.Свойства полей. Определение типа данных, ключей, индексов.
  • 11.Связывание таблиц в субд access. Логическая схема и обеспечение ссылочной целостности данных.
  • 12.Средства реализации запросов в субд access. Виды запросов.
  • 5.2.3 Запрос к связанным таблицам
  • 5.2.4 Запросы удаления
  • 13.Реализация запросов с групповыми операциями и вычисляемыми полями. Примеры.
  • 14.Реализация запросов на модификацию и на создание таблицы.
  • 15.Стандарты современных реализаций языка sql. Основные разделы и их наполнение в sql-Jet.
  • 16.Общий формат select-инструкции (запроса на выборку). Пример реализации.
  • 17.Пример qbe- и sql–реализации перекрестного запроса.
  • 18.Создание интерфейса приложения в субд access. Работа в конструкторе форм. Разделы, элементы управления, свойства.
  • 19.Создание вложенных sql-запросов. Пример реализации.
  • 20.Программы сервиса субд access.
  • 21.Защита и администрирование бд средствами субд access.
  • 22.Использование макросов, отчетов и страниц доступа к данным в приложениях ms access хр.
  • 23.Система программирования Matlab: общая характеристика. Пакеты расширения и специализированные приложения: назначения и возможности. Подсистема Simulink.
  • 24.Структуры данных и основные структуры управления в системе программирования matlab
  • 25.Графические средства системы matlab. Работа с инструментом lti-Viewer графического анализа линейных систем управления.
  • 26.Этапы построения модели в подсистеме Simulink. Элементы технологии визуально-блочного моделирования. Настройка параметров моделирования и параметров блоков.
  • 27.Общее описание блоков библиотеки simulink.
  • 28.Реализация принципа иерархии в Simulink – моделях посредством блоков портов и подсистем. Маскирование подсистем.
  • 29.Компоненты виртуального прибора и их сборка в приложение в среде LabView. Основные элементы управления и индикаторы LabView и их соединение на блок-диаграмме.
  • 19.Создание вложенных sql-запросов. Пример реализации.

    С помощью SQL можно вкладывать запросы внутрь друг друга. Обычно внутренний запрос генерирует значение, которое проверяется в предикате внешнего запроса (в предложении WHERE или HAVING), определяющего, верно оно или нет. Совместно с подзапросом можно использовать предикат EXISTS, который возвращает истину, если вывод подзапроса не пуст.

    В сочетании с другими возможностями оператора выбора, такими как группировка, подзапрос представляет собой мощное средство для достижения нужного результата. В части FROM оператора SELECT допустимо применять синонимы к именам таблицы, если при формировании запроса нам требуется более чем один экземпляр некоторого отношения. Синонимы задаются с использованием ключевого слова AS, которое может быть вообще опущено. Поэтому часть FROM может выглядеть следующим образом:

    FROM Rl AS A, Rl AS В

    FROM Rl A. Rl В:

    оба выражения эквивалентны и рассматриваются как применения оператора SELECT к двум экземплярам таблицы R1.

    Например, покажем, как выглядят на SQL некоторые запросы к БД «Сессия»:

     Список тех, кто сдал все положенные экзамены.

    WHERE Оценка > 2

    HAVING COUNT(*) = (SELECT COUNT(*)

    WHERE R2.Группа=R3.Группа AND ФИОа.ФИО)

    Здесь во встроенном запросе определяется общее число экзаменов, которые должен сдавать каждый студент, обучающийся в группе, в которой учится данный студент, и это число сравнивается с числом экзаменов, которые сдал данный студент.

     Список тех, кто должен был сдавать экзамен по БД, но пока еще не сдавал.

    SЕLЕСТ ФИО

    WHERE R2.Fpynna=R3.Группа AND Дисциплина = "БД" AND NOT EXISTS

    (SELECT ФИО FROM Rl WHERE ФИО=а.ФИО AND Дисциплина = "БД")

    Предикат EXISTS (SubQuery) истинен, когда подзапрос SubQuery не пуст, то есть содержит хотя бы один кортеж, в противном случае предикат EXISTS ложен.

    Предикат NOT EXISTS обратно - истинен только тогда, когда подзапрос SubQuery пуст.

    Обратите внимание, каким образом NOT EXISTS с вложенным запросом позволяет обойтись без операции разности отношений. Например, формулировка запроса со словом «все» может быть выполнена как бы с двойным отрицанием. Рассмотрим пример базы, которая моделирует поставку отдельных деталей отдельными поставщиками, она представлена одним отношением SP «Поставщики-детали» со схемой

    SP (Номер_поставщика. номер_детали) Р (номер_детали. наименование)

    Вот каким образом формулируется ответ на запрос: «Найти поставщиков, которые поставляют все детали».

    SELECT DISTINCT НОМЕР_ПОСТАВЩИКА FROM SP SP1 WHERE NOT EXISTS

    (SELECT номер_детали

    FROM P WHERE NOT EXISTS

    (SELECT * FROM SP SP2

    WHERE SР2.номер_поставщика=SР1.номер_поставщика AND

    sр2.номер_детали = Р.номер_детали)):

    Фактически мы переформулировали этот запрос так: «Найти поставщиков таких, что не существует детали, которую бы они не поставляли». Следует отметить, что этот запрос может быть реализован и через агрегатные функции с подзапросом:

    SELECT DISTINCT Номер_поставщика

    GROUP BY Номер_поставщика

    HAVING CounKDISTINCT номер_детали) =

    (SELECT Count(номер_детали)

    В стандарте SQL92 операторы сравнения расширены до многократных сравнений с использованием ключевых слов ANY и ALL. Это расширение используется при сравнении значения определенного столбца со столбцом данных, возвращаемым вложенным запросом.

    Ключевое слово ANY, поставленное в любом предикате сравнения, означает, что предикат будет истинен, если хотя бы для одного значения из подзапроса предикат сравнения истинен. Ключевое слово ALL требует, чтобы предикат сравнения был бы истинен при сравнении со всеми строками подзапроса.

    Например, найдем студентов, которые сдали все экзамены на оценку не ниже чем «хорошо». Работаем с той же базой «Сессия», но добавим к ней еще одно отношение R4, которое характеризует сдачу лабораторных работ в течение семестра:

    R 1 = (ФИО, Дисциплина, Оценка);

    R 2 = (ФИО, Группа);

    R 3 = (Группы, Дисциплина)

    R 4 = (ФИО, Дисциплина, Номер_лаб_раб, Оценка);

    Select R1.ФИО From R1 Where 4 > = All (Select Rl.Оценка

    Where R1.Фио = R11.Фио)

    Рассмотрим еще один пример:

    Выбрать студентов, у которых оценка по экзамену не меньше, чем хотя бы одна оценка по сданным им лабораторным работам по данной дисциплины:

    Select R1.Фио

    From R1 Where R1.Оценка >= ANY (Select R4.Оценка

    Where Rl.Дисциплина = R4. Дисциплина AND R1.Фио = R4.Фио)


    Вложенные запросы (подзапросы) в SQL Oracle

    1.Цели лабораторной работы

      Изучить возможности SQL Oracle по формулировке и обработке подзапросов.

      Приобрести практический опыт по формулировке и обработке подзапросов с использованием SQL*Plus.

    2.Теоретические основы

    Запрос – это операция, которая позволяет отыскивать данные из одной или несколько таблиц. При наличии вложенных запросов запрос верхнего уровня называется предложением SELECT, а запрос, вложенный в предложение SELECT называется подзапросом. Таким образом, подзапрос (вложенный запрос) – это запрос, результат которого передается в качестве аргумента в другой запрос. Подзапросы позволяют связывать в единое целое несколько запросов.

    Подзапросы используются для:

      определения множества строк, который должны быть вставлены в целевую таблицу в предложениях INSERT или CREATE TABLE;

      определения одного или более значений, присваиваемых существующим строка в предложении UPDATE;

      получения значений для фраз WHERE, HAVING или START WITH в предложениях SELECT, UPDATE, и DELETE;

      определения значений указанного столбца в списке INSERT ... VALUES;

      определения таблицы, которая используются соответствующим запросом.

    Это производится путем размещения подзапроса во фразе FROM соответствующего запроса как если бы это было именем таблицы. Вы можете также использовать таким образом подзапросы вместо таблиц в предложениях INSERT, UDPATE и DELETE.

    Используемые таким образом подзапросы могут использовать переменные связывания (correlation variables), однако только такие, которые определены только в самом подзапросе, ссылки на внешние переменные не допустимы. Внешние ссылки (подзапросы с левой корреляцией - left-correlated subqueries) допустимы только во фразе FROM предложения SELECT .

    Подзапрос дает ответ на содержательные запросы, имеющие сложную структуру. Например, для определения, кто работает на кафедре Иванова, вы сначала используете подзапрос для определения кафедры, на которой работает Иванов, а затем отвечаете на основной запрос путем формулировки предложения SELECT.

    Подзапрос может содержать другие подзапросы. Oracle не ограничивает глубину вложенности подзапросов.

    Если таблица в подзапросе имеет такое же имя, что и таблица внешнего запроса, то для ссылки на столбцы внешнего запроса их необходимо уточнять именем таблицы или алиасом таблицы. Чтобы ваши запросы было легче воспринимать, всегда квалифицируйте столбцы в подзапросе именем или алиасом таблицы.

    Oracle выполняет корреляционные (связанный) подзапрос , когда подзапрос ссылается на столбец таблицы внешнего запроса. Связанный подзапрос вычисляется для каждой строки, обрабатываемой внешним предложением. Внешним предложением может быть SELECT, UPDATE или DELETE.

    Связанный подзапрос дает ответы на такие содержательные запросы, ответы которых требуют вычисления подзапросов для каждой строки внешнего запроса. Например, связанный подзапрос используется для определения преподавателей, которые зарабатывают больше, чем средняя зарплата по кафедре. В этом случае связанный подзапрос для каждого преподавателя вычисляет среднюю зарплату на его кафедре.

    2.1.Подзапрос во фразе WHERE

    2.1.1.Подзапрос в простом условии сравнения

    Синтаксис:

    Описание:

    При использовании простых условий сравнения с подзапросом во фразе WHERE применяются следующие правила:

      Подзапрос должен возвращать единственную строку.

      Если левая часть равна expr , то подзапрос должен возвращать единственную строку с единственным значением с типом, совместимым с типом expr .

      Если левая часть является списком выражений (expr_list ), то подзапрос должен возвращать единственную строку со списком значений, который соответствует по количеству и типу значениям из expr_list . В этом случае оператор сравнения дает TRUE, если каждое значение в expr_list равно (в случае =) или не равно (в случае!=, ^=,) каждому значение, возвращаемому подзапросом.

    Примеры :

    1. Выбрать кафедры, которые располагаются в том же корпусе, что факультет информатики:

    WHERE Building = (SELECT Building

    WHERE UPPER(Name) = "INFORMATICS");

    2. Выбрать факультеты, чьи фонды меньше фонда кафедры CAD:

    WHERE UPPER(Name) = "CAD");

    3. Выбрать преподавателей, у которых salary + commission превышает более чем на 100 половину salary + commission преподавателя Bill:

    WHERE Salary + Commission + 100 > (SELECT (Salary + Commission) / 2

    WHERE UPPER(Name) = "BILL");

    4. Выбрать преподавателей, которые работают на той же кафедре, что и Bill и занимают ту же должность, что и Bill:

    WHERE (DepNo, Post) = (SELECT DepNo, Post

    WHERE UPPER(Name) = "BILL");

    2.1.2.Подзапрос в условии сравнения групп

    Синтаксис:

    Описание:

    При использовании условий сравнения групп с подзапросом во фразе WHERE применяются следующие правила:

      Подзапрос может возвращать ноль или более строк.

      Если левая часть равна expr , то подзапрос должен возвращать строки с единственным значением, которые совместимы по типу с expr .

      Если левая часть равна expr_list , то подзапрос должен возвращать строки со списком значений, который соответствует по количеству и типу с expr_list .

    ANY и SOME эквивалентны и сравнивают значение слева с каждым значением списка справа, возвращаемого подзапросом. Подзапрос может вернуть ноль или более строк. Условие равно TRUE, если по крайней мере одна строка подзапроса удовлетворяет условию (соответствует оператору сравнения) по отношению к значению (списку значений) определенному левым операндом, в противном получаем FALSE. Если подзапрос не возвращает строк, то получаем FALSE.

    ALL сравнивают значение слева с каждым значением списка справа, возвращаемого подзапросом. Дает TRUE, если ВСЕ строки, возвращаемые подзапросом, удовлетворяют условию (соответствуют оператору сравнения) по отношению к значению (списку значений) определенному левым операндом, в противном получаем FALSE. Если подзапрос не возвращает строк, то получаем TRUE

    Примеры:

    1. Выдать кафедры, фонд которых больше фонда по крайней мере одного из факультетов:

    WHERE Fund >

    ANY, ALL и агрегатные функции . Обратите внимание, что левое значение меньше, чем максимальное значение из множества, задаваемого правым операндом”, а оператор >ANY эквивалентен следующему утверждению “левое значение больше, чем минимальное значение из множества, задаваемого правым операндом ”. Поэтому операторы ANY могут быть выражены через функции MAX и MIN в подзапросе. В свою очередь, ALL) эквивалентно утверждению: «левое значение меньше (больше), чем минимальное (максимальное) значение из множества, задаваемого правым операндом ».

    2. Выдать кафедры, фонд которых больше фонда по крайней мере одного из факультетов:

    WHERE Fund > ANY (SELECT Fund FROM FACULTY);

    WHERE Fund > (SELECT MIN(Fund) FROM FACULTY);

    WHERE Rating >ALL (SELECT Rating

    FROM SGROUP, DEPARTMENT

    WHERE SGROUP.DepNo = DEPARTMENT.DepNo AND

    UPPER(DEPARTMENT.Name) = "DBMS" AND SGROUP.Course = 5);

    2.1.3.Подзапрос в условии проверки вхождения элемента во множество

    Синтаксис:

    Описание:

    Это условие в таком синтаксисе проверят вхождение элемента (списка элементов) во множество (множество списков), создаваемое подзапросом.

    Пример:

    1. Выбрать преподавателей, которые имеют лекции по крайней мере одному такому предмету, по которым читает лекции преподаватель Bill:

    FROM TEACHER T, LECTURE L

    WHERE T.TchNo = L.TchNo AND

    SbjNo IN (SELECT SbjNo

    FROM TEACHER TCH, LECTURE LEC

    WHERE TCH.TchNo = LEC.TchNo AND UPPER(TCH.Name) = "BILL");

    2.1.4.Подзапрос в условии EXISTS

    Синтаксис:

    Описание:

    Дает TRUE, если подзапрос возвращает по крайней мере одну строку.

    Так как EXISTS обычно используется в связанных подзапросах, мы его обсудим подробнее позже.

    2.2.Связанные подзапросы

    Для того, чтобы связать подзапрос с внешним запросом (предложением), необходимо в подзапросе была ссылка на столбец внешнего запроса. Подзапрос вычисляется для каждой строки, обрабатываемой внешним запросом (предложением). В качестве внешнего предложения могут выступать SELECT, UPDATE или DELETE.

    Следующие примеры дают общий синтаксис использования связанных подзапросов:

    SELECT select_list

    FROM table1 t_alias1

    WHERE expr operator

    (SELECT column_list

    FROM table2 t_alias2

    WHERE t_alias1.column operator t_alias2.column);

    UPDATE table1 t_alias1

    FROM table2 t_alias2

    DELETE FROM table1 t_alias1

    WHERE column operator

    FROM table2 t_alias2

    WHERE t_alias1.column = t_alias2.column);

    2.2.1.Связанные подзапросы во фразе WHERE

    Примеры:

    1. Выдать преподавателей, которые имеют по крайней мере одну лекцию:

    WHERE EXISTS (SELECT *

    Здесь в условии LECTURE.TchNo = TEACHER.TchNo подзапроса мы ссылаемся на внешний запрос. Поэтому подзапрос является связанным.

    2. Выдать преподавателей, которые не имеют ни одной лекции:

    WHERE NOT EXISTS (SELECT *

    WHERE LECTURE.TchNo = TEACHER.TchNo);

    2.3.Простые и связанные подзапросы во фразе HAVING

    Вы можете использовать простые и связанные подзапросы во фразе HAVING.

    Если вы используете связанный подзапрос в фразе HAVING, то в подзапросе можно ссылаться на те столбцы внешнего запроса, которые могут использоваться в фразе HAVING (обычно это столбцы, по которым производится группирование).

    Примеры:

    1. Перечислить факультеты, у которых сумма фондов финансирования всех их кафедр превышает более чем на 20000 фонд финансирования той кафедры факультета, которая имеет максимальный фонд.

    FROM FACULTY F1, DEPARTMENT D1

    WHERE F1.FacNo = D1.FacNo

    GROUP BY F1.Name

    HAVING SUM(D1.Fund) > (SELECT 200000 + MAX(D2.Fund)

    FROM FACULTY F2, DEPARTMENT D2

    WHERE F2.FacNo = D2.FacNo AND F1.Name = F2.Name);

    Вложенные запросы – это запросы, вызываемые другим, внешним, запросом. Они всегда заключаются в круглые скобки и им обязательно должен присваиваться псевдоним. Некоторые считают вложенный запрос аналогом временных таблиц, однако эти два инструмента имеют ряд отличий, которые мы рассмотрим в данной статье.

    Вложенный запрос видит только себя, он не видит внешний запрос. Это значит, что нельзя, например, установить во вложенном запросе условие по значению поля внешнего запроса.

    Большинство представленных запросов не имеют какой-либо ценности и могли бы быть выполнены проще. Они приведены только для иллюстрации механизма вложенных запросов.

    Вложенные запросы могут использоваться в конструкции ИЗ:

    Запрос. Текст= "ВЫБРАТЬ
    ВложенныйЗапрос.Поле1,
    ВложенныйЗапрос.Поле2
    ИЗ
    (ВЫБРАТЬ
    Таблица1.Поле1,
    Таблица1.Поле2
    ИЗ ТаблицаДанных КАК Таблица1) КАК ВложенныйЗапрос"
    ;

    В том числе в соединениях:

    Запрос. Текст= "ВЫБРАТЬ
    ВложенныйЗапрос.Наименование,

    ИЗ
    (ВЫБРАТЬ
    Контрагенты.Ссылка КАК Ссылка,
    Контрагенты.Наименование КАК Наименование
    ИЗ
    Справочник.Контрагенты КАК Контрагенты) КАК ВложенныйЗапрос
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЧерныйСписок.СрезПоследних КАК ЧерныйСписокСрезПоследних
    ПО ВложенныйЗапрос.Ссылка = ЧерныйСписокСрезПоследних.Котрагент"
    ;

    И в условиях запроса со сравнением В или В ИЕРАРХИИ:

    Запрос. Текст= "ВЫБРАТЬ
    ЧерныйСписокСрезПоследних.Состояние
    ИЗ
    РегистрСведений.ЧерныйСписок.СрезПоследних КАК ЧерныйСписокСрезПоследних
    ГДЕ
    ЧерныйСписокСрезПоследних.Котрагент В
    (ВЫБРАТЬ ПЕРВЫЕ 10
    Контрагенты.Ссылка
    ИЗ
    Справочник.Контрагенты КАК Контрагенты)"
    ;

    При этом количество выбираемых полей вложенного запроса должно соответствовать количеству операндов в левой части выражения В или В ИЕРАРХИИ.

    Существует мнение, что вложенные запросы в сложных конструкциях выполняются платформой 1С нерационально, требуют бОльших ресурсов и времени, нежели те же самые запросы, выполненные иначе, без использования вложенных запросов. Однако в ряде случаев, обойтись без вложенных запросов невозможно.

    Вместе с тем, обычно эффективнее работает один большой запрос с вложенными, чем последовательность запросов из модуля.

    Практически всегда альтернативой вложенному запросу является использование временных таблиц. Этот инструмент имеет ряд преимуществ:

    1. Запрос становится более структурированным, его легче читать.
    2. Результат, загруженный во временную таблицу можно использовать несколько раз, и при этом нет необходимости заново выполнять запрос, чтобы этот результат получить. А вложенный запрос будет каждый раз выполняться заново, излишне загружая ресурсы системы.

    Подведем итог: вложенные запросы лучше всего применять в достаточно простых конструкциях, при этом использовать их стоит только тогда, когда по-другому задачу не решить; в сложных запросах лучше использовать временные таблицы.

    В прошлом уроке мы столкнулись с одним неудобством. Когда мы хотели узнать, кто создал тему "велосипеды", и делали соответствующий запрос:

    Вместо имени автора, мы получали его идентификатор. Это и понятно, ведь мы делали запрос к одной таблице - Темы, а имена авторов тем хранятся в другой таблице - Пользователи. Поэтому, узнав идентификатор автора темы, нам надо сделать еще один запрос - к таблице Пользователи, чтобы узнать его имя:

    В SQL предусмотрена возможность объединять такие запросы в один путем превращения одного из них в подзапрос (вложенный запрос). Итак, чтобы узнать, кто создал тему "велосипеды", мы сделаем следующий запрос:

    То есть, после ключевого слова WHERE , в условие мы записываем еще один запрос. MySQL сначала обрабатывает подзапрос, возвращает id_author=2, и это значение передается в предложение WHERE внешнего запроса.

    В одном запросе может быть несколько подзапросов, синтаксис у такого запроса следующий: Обратите внимание, что подзапросы могут выбирать только один столбец, значения которого они будут возвращать внешнему запросу. Попытка выбрать несколько столбцов приведет к ошибке.

    Давайте для закрепления составим еще один запрос, узнаем, какие сообщения на форуме оставлял автор темы "велосипеды":

    Теперь усложним задачу, узнаем, в каких темах оставлял сообщения автор темы "велосипеды":

    Давайте разберемся, как это работает.

    • Сначала MySQL выполнит самый глубокий запрос:

    • Полученный результат (id_author=2) передаст во внешний запрос, который примет вид:

    • Полученный результат (id_topic:4,1) передаст во внешний запрос, который примет вид:

    • И выдаст окончательный результат (topic_name: о рыбалке, о рыбалке). Т.е. автор темы "велосипеды" оставлял сообщения в теме "О рыбалке", созданной Сергеем (id=1) и в теме "О рыбалке", созданной Светой (id=4).
    Вот собственно и все, что хотелось сказать о вложенных запросах. Хотя, есть два момента, на которые стоит обратить внимание:
    • Не рекомендуется создавать запросы со степенью вложения больше трех. Это приводит к увеличению времени выполнения и к сложности восприятия кода.
    • Приведенный синтаксис вложенных запросов, скорее наиболее употребительный, но вовсе не единственный. Например, мы могли бы вместо запроса

      написать

      Т.е. мы можем использовать любые операторы, используемые с ключевым словом WHERE (их мы изучали в прошлом уроке).

    Часто при выборке данных бывает необходимо объединить информацию из нескольких связанных таблиц. Сделать это можно посредством вложенных запросов, либо при помощи соединения с помощью SQL.

    Вложенные запросы

    В рамках нашего примера, допустим, что нам понадобилось узнать имена узлов, которые посещали сайт www.dom2.ru. Требуемую информацию можно получить запросом:

    SELECT hst_name FROM hosts WHERE hst_pcode IN (SELECT vis_hstcode FROM visits, sites WHERE (sit_pcode = vis_sitcode) AND (sit_name LIKE "www.dom2.ru"));

    Рассмотрим этот запрос более пристально. Первый оператор SELECT нужен для выборки имен узлов. Чтобы выбрать требуемые нам имена, в запросе указана секция WHERE, в которой первичный ключ таблицы «Узлы» (hst_pcode) проверяется на принадлежность множеству (оператор IN). Судя по всему, множество для проверки на принадлежность должен вернуть второй оператор SELECT, находящийся в скобках. Рассмотрим его отдельно:

    SELECT vis_hstcode FROM visits, sites WHERE (sit_pcode = vis_sitcode) AND (sit_name LIKE "www.dom2.ru")

    Для содержимого таблиц в нашем примере, вложенный запрос вернет следующее множество значений

    Соединение с помощью SQL

    Как и говорилось выше, одним из способов выборки данных из нескольких таблиц является соединение таблиц с помощью SQL. Основная цель такого соединения - создание нового отношения, которое будет содержать данные из двух или более исходных отношений.

    Внутреннее соединение

    Рассмотрим пример:

    SELECT hst_name, sit_name, vis_timestamp FROM hosts, visits, sites WHERE (hst_pcode = vis_hstcode) AND (vis_sitcode = sit_pcode)

    Данный запрос вернет следующие данные

    hst_name sit_name vis_timestamp
    ws1 www.dom2.ru 2012-08-01 07:59:58.209028
    ws1 www.vkontakte.ru 2012-08-01 08:00:10.315083
    1-1 www.vkontakte.ru 2012-08-01 08:00:20.025087
    1-2 www.opennet.ru 2012-08-01 08:00:26.260159

    В этом примере из трех таблиц (hosts, visits, sites) выбирается по одному полю и создается новая таблица, в которой будут собраны имена узлов, посещаемых сайтов и время посещений. Представление соединяемых данных регламентируется условиями в операторе WHERE. Видно, что имеется два условия, которые соединяют три таблицы. Поскольку в таблице посещений (visits) вместо имени узла и наименования сайта указаны их идентификаторы, при соединении таблиц мы добавляем условие, чтобы связать по идентификаторам данные и тогда все встанет на свои места. Если по каким-то причинам, вопреки ссылочной целостности в таблице посещений будут находиться записи с идентификатором несуществующего узла или сайта, они не появятся в результирующем наборе данных запроса в этом примере.

    Указанный выше пример немного упрощен и из-за немного упрощения теряется наглядность. Более наглядная форма запроса, соединяющего несколько таблиц и возвращающего тот же самый набор данных будет иметь вид

    SELECT hst_name, sit_name, vis_timestamp FROM hosts JOIN visits ON (hst_pcode = vis_hstcode) JOIN sites ON (vis_sitcode = sit_pcode);

    В запросе присутствует два оператора JOIN… ON. Поскольку «Join» можно перевести как «соединение» или «объединение», этот пример более красноречив. Если попытаться перевести текст SQL-запроса на русский, получится что-то вроде

    ВЫБРАТЬ (поля) hst_name, sit_name, vis_timestamp ИЗ (таблицы) hosts СОЕДИНИВ (с таблицей) visits ПО (условию) (hst_pcode = vis_hstcode) СОЕДИНИВ (с таблицей) sites ПО (условию) (vis_sitcode = sit_pcode);

    Русские слова в круглых скобках добавлены для облегчения понимания работы запроса. Вы можете использовать любой из вышеперечисленных способов написания запросов.

    Внешнее соединение

    Использованные выше способы соединения таблиц называются внутреннее соединение (inner join). У такого способа соединения есть недостатки. Например, если у нас не было посещений на один из сайтов, либо один из узлов не совершил ни одного посещения, то в результирующем наборе данных сайт или узел будут отсутствовать. В примере выше видно, что сайт www.yandex.ru отсутствует в данных, равно как и узел 1-3.Иногда это нежелательно и в таких случаях используют внешнее соединение (outer join). Внешнее соединение может быть левым (left join) и правым (right join). Сторона соединения (левая или правая) соответствует таблице, данные из которой будут выбираться полностью. Таким образом, при использовании LEFT JOIN, данные из таблицы слева от оператора JOIN будут выбираться полностью. Закрепим это примером. Допустим, надо выбрать ВСЕ узлы и связанные с ними посещения. Сделать это можно посредством запроса

    SELECT hst_name, vis_timestamp FROM hosts LEFT JOIN visits ON (hst_pcode = vis_hstcode);

    Обратите внимание на данные, которые вернутся в ответ на запрос

    hst_name vis_timestamp
    ws1 2012-08-01 07:59:58.209028
    ws1 2012-08-01 08:00:10.315083
    1-1 2012-08-01 08:00:20.025087
    1-2 2012-08-01 08:00:26.260159
    1-3

    Видно, что узлу 1-3 не соответствует ни одно посещение, но он все равно в списке. Аналогичным образом работает RIGHT JOIN. Запрос, который вернет тот же набор данных можно записать с использованием RIGHT JOIN:

    SELECT hst_name, vis_timestamp FROM visits RIGHT JOIN hosts ON (hst_pcode = vis_hstcode);

    В этом случае, надо сменить LEFT JOIN на RIGHT JOIN и поменять местами таблицы visits и hosts в запросе.

    Использование UNION

    Иногда бывает нужно получить два списка записей из таблиц в виде одного. Для этой цели может быть использовано ключевое слово UNION, которое позволяет объединить результирующие наборы данных двух запросов в один набор данных. Допустим, надо получить некоторый список, в котором были бы узлы сети и имена сайтов. Таблицы разные, соответственно и запросы будут разными. Как объединить все в один набор данных? Легко, но есть определенные требования к такому «склеиванию» запросов:

    § запросы должны содержать одинаковое число полей;

    § типы данных полей объединяемых запросов так же должны совпадать.

    В остальном же, использование UNION не является сложным. Например, чтобы получить список имен узлов и имен сайтов в виде одного набора данных, выполним такой запрос:

    SELECT hst_name AS name FROM hosts UNIONSELECT sit_name AS name FROM sites;

    При таком подходе возможны проблемы с сортировкой записей. Чтобы список сайтов шел после списка узлов, можно умышленно добавить целочисленное поле, где указывать номер, который будет участвовать в сортировке. Например

    SELECT 1 AS level, hst_name AS name FROM hosts UNIONSELECT 2 AS level, sit_name AS name FROM sitesORDER BY level, name;

    Условия EXISTS и NOT EXISTS

    Иногда бывает необходимо выбрать из таблицы записи, которым соответствуют (или не соответствуют) записи в других таблицах. Допустим, что нам нужен список сайтов, на которые не было посещений. Получить такой список можно запросом

    SELECT sit_name FROM sites WHERE ((SELECT COUNT(*) FROM visits WHERE vis_sitcode = sit_pcode) = 0);

    Для нашего примера, список будет коротким:

    sit_name
    www.yandex.ru

    Запрос работает следующим образом:

    § из таблицы sites выбирается код сайта и его наименование;

    § код сайта передается во вложенный запрос, который считает записи с этим кодом в таблице visits;

    § функция COUNT(*) сосчитает записи и вернет их количество, который будет передано в условие;

    § при истинности условия (количество записей равно 0) имя сайта добавляется в список.

    Если некоторым этот запрос покажется непонятным, то можно добиться тех же результатов посредством запроса с использованием NOT EXISTS:

    SELECT sit_name FROM sites WHERE NOT EXISTS (SELECT vis_pcode FROM visits WHERE vis_sitcode = sit_pcode);

    Выражение NOT EXISTS (на мой взгляд) вносит дополнительную ясность и более доступно для понимания. Аналогично работает выражение EXISTS, которое проверяет наличие записей.

    Представления (VIEW)

    Представления (VIEW) используются для обеспечения возможности сохранения сложного запроса на сервере под указанным именем. Допустим, вам часто приходится запрашивать данные, набирая объемный запрос. Если подойти к проблеме прогрессивно, то можно создать представление. Делается это несложно. Например,

    CREATE VIEW show_dom2 ASSELECT hst_name FROM hosts WHERE hst_pcode IN (SELECT vis_hstcode FROM visits, sites WHERE (sit_pcode = vis_sitcode) AND (sit_name LIKE "www.dom2.ru"));

    Собственно, всё. Внимательный наблюдатель, наверное, заметил, что по-сути, можно взять запрос и в самом начале добавить слова «CREATE VIEW <имя> AS». Именно по такому принципу можно рекомендовать создание представлений. Создайте запрос, убедитесь в его работоспособности и потом допишите все необходимое, чтобы сохранить этот запрос на сервере как представление. Единственный недостаток использования представлений заключается в том, что некоторые особо сложные приемы написания запросов могут не работать в представлениях. К сожалению, в документации по postgreSQL очень мало сведений о представлениях и однозначно узнать, что можно использовать, а что нет вы сможете методом проб и ошибок. Сохранив запрос на сервере как представление, вы сможете выполнить его сколько угодно раз, запросом типа

    SELECT * FROM show_dom2;

    Важно отметить, что при выполнении запроса, который выбирает данные из представления - данные выбираются из таблиц посредством запроса, который хранится в представлении. Представление является полностью динамическим и данные, возвращаемые представлением будут актуальными при обновлении данных в таблицах. Удалить представление можно запросом типа

    DROP VIEW show_dom2;

    Заключение

    данные отчет запрос заказ

    В данной курсовой работе была разработана база данных "Склад канцтоваров", содержащая всю необходимую информацию о товарах, покупателях, поставщиках и заказах. С помощью моей базы можно без затруднений и специальных знаний вести базу данных, которая позволяет делать все операции с клиентами, заказами, производителями. То есть добавлять, изменять, обновлять, удалять и просматривать все имеющиеся и вводимые данные. На основе базы данных были составлены запросы и отчеты.

    ЗАКЛЮЧЕНИЕ


    СПИСОК ЛИТЕРАТУРЫ


    ПРИЛОЖЕНИЕ А


    ПРИЛОЖЕНИЕ Б