Создание запросов

advertisement
Создание запросов в «OpenOffice».
Создание простых запросов




В левом поле главного окна выбрать элемент «Запросы»
В поле «Задачи» выбрать элемент «Создать запрос в режиме дизайна»
Выбрать в открывшемся окне таблицу «Студент», из которой будем выбирать данные
Нажать кнопки «Добавить», «Закрыть».
Открывается конструктор таблиц. В верхнем поле отображаются таблицы, из которых
будет осуществляться выборка данных и связи между ними. В нижнем поле настраиваются
выводимые колонки таблиц.
 Двойным щелчком на нужных полях добавляем колонки в нижнее поле.
 Для выполнения запроса нажать кнопку «Выполнить запрос» на панели инструментов. В
верхней части конструктора запросов проявляется область вывода результатов, в которую
выводятся все записи таблицы «Студент»
Чтобы отсортировать фамилии студентов по алфавиту надо подвести указатель мыши к
полю «Сортировка» в колонке «ФИО», дважды щелкнуть левой кнопкой мыши и выбрать из
раскрывшегося списка «по возрастанию». Разумеется, надо заново выполнить запрос.
Если добавить сортировку по группам получим список, отсортированный по группам,
причем в пределах группы студенты отсортированы по ФИО. Всегда при сортировке левая
колонка имеет приоритет.
Чтобы поменять порядок колонок, нужно нажать левую кнопку мыши в заголовке (серой
строке) таблицы колонок, не отпуская ее, переместить указатель мыши в область заголовка другой
колонки и отпустить кнопку мыши.
Если нас интересуют студенты только одной группы в поле «Критерий» колонки «Группа»
вводим шифр нужной группы. Выполните запрос. Обратите внимание, что конструктор запросов
автоматически заключил заданную строку в апострофы 'АК1-11'.
Чтобы отобрать студентов групп, начинающихся на подстроку «АК» следует задать в поле
критерий для колонки «группа» строку like 'АК*'
На месте символа «*» может стоять 0 или более любых символов.
Чтобы найти студентов с именем «Иван» воспользуемся следующим выражением
like '* Иван *' Обратите внимание на пробелы между «*» и именем. Если этого не
сделать под условие попадут все «Ивановы» и «Ивановичи».
Удалите все условия.
Зададим условие на дату рождения >= 11.11.1981. Выполните запрос. Обратите внимание,
что конструктор запросов автоматически добавил справа и слева от даты символ «#».
Добавим условие в поле «ИЛИ». Выполните запрос.
Получили студентов из группы 'АК1-11' с датой рождения >= #11.11.1981# а так же всех
студентов группы 'АК3-11'. Как понять, что получится в результате запроса?
Нажмите на панели инструментов кнопку «включить / выключить вид дизайна».
Две нижних области заменяются текстовым полем с запросом на языке SQL.
SELECT "Группа", "№зачетки", "ФИО", "Дата рождения" FROM "Студент" AS
"Студент" WHERE ( "Группа" = 'АК1-11' AND "Дата рождения" >= {D '198111-11' } OR "Группа" = 'АК3-11' ) ORDER BY "Группа" ASC, "ФИО" ASC
Когда вы нажимаете кнопку «выполнить» конструктор запросов формирует такую строку,
и передает ее драйверу СУБД. Драйвер передает ее на сервер СУБД, (если надо, по сети).
Результаты запроса передаются обратно через драйвер СУБД конструктору, который отображает
их. Именно SQL является стандартным языком для всех СУБД. Таким образом, вы можете легко
перейти на другую СУБД другого производителя. К сожалению, некоторые конструкции нечетко
прописаны в стандарте, в результате существуют диалекты языка SQL. Так, что при смене СУБД
обычно требуется тестирование и внесение некоторых изменений.
Но вернемся к нашему запросу. Во первых, можно заметить, что для критериев отбора, у
которых не задана операция отношения, используется отношение «равно». Во вторых, условия
отбора, заданные в разных колонках соединены логической операцией «AND». В третьих, условия
в разных строках условия соединены логической операцией «OR». Отбираются только записи, для
которых выполняется условие, заданное в секции «WHERE».
Если нужно, отобрать студентов групп 'АК1-11' и 'АК3-11' с датой рождения больше
заданной, поправьте условие
SELECT "группа", "№зачетки", "ФИО", "Дата рождения" FROM "студент" AS
"студент" WHERE ( "Дата рождения" >= {D '1980-04-03' } AND ("группа" =
'АК1-11' OR "группа" = 'АК3-11') ) ORDER BY "группа" ASC, "ФИО" ASC
Если снова нажать на кнопку «включить / выключить вид дизайна». Конструктор
попробует перевести заданное условие в табличную форму. Но бывают случаи некорректного
преобразования.
Удалите все условия на группу.
Отберем теперь всех студентов с датой рождения в заданном диапазоне. Нам нужно
получить условие
"Дата рождения">={D '1980-01-01'} AND "Дата рождения"<{D '1981-01-01'}
Чтобы сформировать это условие в конструкторе, добавим еще одно поле «Дата рождения»
и зададим в ней второе условие.
Чтобы в результатах запроса не появилась вторая колонка колонку «Дата рождения»
снимите отметку «Видимый» в дублирующей колонке.
Вычисление значений выражений
Удалите все условия.
К значениям полей можно применять различные функции, например, если мы хотим
получить год рождения каждого студента, надо ввести вместо имени поля выражение:
YEAR("Дата рождения"). Обратите внимание, что имя поля заключается в кавычки. Не
забудьте поставить отметку «Видимый»
Чтобы в результатах запроса в заголовке нашей новой колонки выводилось не заданное
выражение, а осмысленная строка, введите нужный текст в поле «псевдоним» нашей колонки.
Кстати, при использовании результатов одного запроса в другом псевдонимы для вычисляемых
колонок надо задавать обязательно.
Месяц можно посчитать с помощью функции MONTH("Дата рождения")
Можно задавать и более сложные выражения. Выведем возраст наших студентов на данный
момент времени. Это можно сделать двумя способами:
YEAR(NOW( )) - YEAR("Дата рождения") – берем год от текущей даты и вычитаем
из него год от даты рождения.
DATEDIFF('year', "Дата рождения", NOW()) – Воспользуемся специальной
функцией. Эта же функция позволяет вычислять длительность интервала в днях:
DATEDIFF('day', "Дата рождения", NOW())
Полный список функций приведен в приложении «Встроенные функции и хранимые
процедуры Hsqldb».
При формировании выпадающего списка часто требуется склеить значения из нескольких
колонок таблицы. Например, если имеются однофамильцы, придется добавить к ФИО номер
зачетки с помощью оператора склеивания строк «||»:
"ФИО" || '/' || "№зачетки" || '/'
Итак, запомните правила:
 Строковые константы заключаются в апострофы 'Иванов'
 Имена таблиц и колонок заключаются в кавычки "ФИО" Внимательно следите за
пробелами и регистром символов.
 Даты заключаются между символами «#»: #11.11.1981#
 Числовые константы записываются, без каких либо знаков: 12345
Работа с NULL значениями
Откройте таблицу «студент» и сотрите у одного из студентов дату рождения. Такие
значения называются «NULL значения». Сохраните запись.
Выполните наш запрос. Результатом выражения оказалась пустая строка.
Попробуйте задать условие на дату. Запись с «NULL» не удовлетворяет ни условию «<=
#01.01.1980#» ни «>= #01.01.1980#», ни, как не странно «<> #01.01.1980#».
Для проверки на NULL значение используйте условия «IS EMPTY» и «NOT IS EMPTY»
Исключение повторяющихся записей
Составим список групп, в которых имеются студенты 1980 года рождения, причем, нас не
интересуют ФИО студентов, только факт наличия студентов в группе.
Создайте новый запрос в режиме дизайна. Добавьте таблицу «Студент». Добавьте колонки
«Группа» и «Дата рождения». Во второй колонке организуйте вычисление выражения
«YEAR("Дата рождения")», задайте критерий отбора 1980, снимите отметку «Видимый».
После выполнения запроса получим:
Почему группа «CM1-11» попала в список 3 раза? Дело в том, что в этой группе три
студента 1980 гола рождения. Чтобы избавится от повторов? Нажмите на панели инструментов
кнопку «Однозначные значения» (крайняя справа). Если кнопка утоплена, исключаются
одинаковые строки в выборке.
Выполните запрос. Теперь повторов нет, а группы оказались отсортированы по алфавиту.
Запрос данных из связанных таблиц
Пусть нам нужно вывести ФИО преподавателей и наименования предметов по всем
экзаменам заданной группы.
Особенностью этого запроса является то, что фамилия преподавателя, наименование
предмета и шифр группы лежат в разных таблицах.
Создайте новый запрос в режиме дизайна. Добавьте таблицы «Преподаватель»,
«Ведомость» и «Предмет». Выбираем таблицу «Ведомость», поскольку в ней есть шифр группы,
но важнее всего, что именно поля этой таблицы ссылаются на записи в таблицах предмет и
преподаватель.
Обратите внимание, что конструктор запросов автоматически добавил связи между
таблицами, пользуясь связями, которые мы создали в конструкторе связей. Если добавленные
таблицы окажутся не связанными, значит, вы не добавили связь между таблицами, или таблицы не
связаны непосредственно, тогда надо добавить таблицу, посредством которой связаны наши
таблицы, хотя из этой таблицы нам и не нужно ни одного поля.
Но вернемся к нашему запросу. Добавьте колонки:
 «ФИО» из таблицы «Преподаватель»
 «Наименование» из таблицы «Предмет»
 «Группа» из таблицы «Ведомость»
Задайте шифр группы в поле «Критерий» колонки «Группа» и выполните запрос.
Не забудьте предварительно ввести данные в таблицы.
Контрольные задачи на простые запросы
1. Составить список групп для заданного факультета.
2. Определить список предметов (в алфавитном порядке), принимавшихся заданным
преподавателем.
3. Вывести номера ведомостей и даты экзаменов, в весеннем семестре заданного года.
4. Создать список групп, сдававших экзамены заданному преподавателю в заданном
месяце.
5. Составить список преподавателей (в алфавитном порядке), принимавших экзамены в
текущем году.
Правое и левое соединение таблиц
Пусть нам надо вывести оценки всех студентов по математике, но не для всех студентов
есть записи в таблице результат.
К сожалению, в конструкторе «OpenOffice.org 3.0» в один запрос такую задачу решить не
удалось. Подготовим вспомогательный запрос, формирующий список оценок по математике.
Создаем новый запрос в режиме дизайна. Добавляем таблицы «Результат» и «Ведомость».
Добавляем колонки «Студент» и «Оценка» из таблицы «Результат». Добавляем колонку
«Предмет» из таблицы «Ведомость». Колонке «Оценка» даем псевдоним «Математика». Для
колонки «Предмет» задаем критерий отбора равный коду математики (Посмотрите в таблице
«Предмет»). Значения в колонке «Предмет» все одинаковые их мы и так знаем, поэтому, снимем
отметку «Видимый».
Сохраним этот запрос под именем «Оценки по Математике».
Создаем новый запрос в режиме дизайна. Добавляем таблицу «Студент». Затем выбираем
кнопку «Запросы» и добавляем наш вспомогательный запрос «Оценки по Математике». Часто
сложный запрос удобно разбить на несколько простых вспомогательных запросов, а затем
использовать их в главном запросе. Обычно, время выполнения от этого не меняется. Перед
выполнением, собирается общий запрос и передается СУБД, которая его оптимизирует.
Внимание! Таблицы надо связать. Для этого надо подвести указатель мыши к полю «№
зачетки» из таблицы «Студент», нажать левую кнопку мыши и, не отпуская ее переместить
указатель мыши на поле «Студент» из вспомогательного запроса, затем отпустить кнопку мыши.
Добавляем колонки «№ зачетки» и «ФИО» из таблицы «Студент». И колонку
«Информатика» из вспомогательного запроса.
Если сейчас выполнить запрос, получим фамилии студентов, сдававших математику и их
оценки. Дело в том, что тип добавляемой связи по умолчанию «Внутреннее объединение». При
таком соединении выводятся только записи, в котором значения в заданных полях совпадают.
Чтобы получить список всех студентов, выполните двойной щелчок мыши на связи между
таблицами и выберите из выпадающего списка «тип» «Правое объединение», нажмите «ОК».
Выполните запрос. Теперь получим полный список студентов и оценки по математике для
тех студентов, которые ее сдавали. У остальных к колонке «Математика» пусто. Если не
получилось, попробуйте «Левое объединение». Какое объединение выбрать, зависит не от
расположения таблиц в среднем окне, а от порядка, в котором их добавляли. И еще одно
замечание, если подсказка в нижней части диалога «Свойства связи» не соответствует результату,
не верь глазам своим.
Одним запросом эту задачу не удалось решить не только потому, что конструктор запросов
в «OpenOffice.org 3.0» не переваривает два правых / левых объединения в одном запросе.
Сохраните полученный запрос под именем «студент - математика» и снимите с него копию
(Ctrl+C, Ctrl+V в главном окне программы). Поэкспериментируем с ним.
Попробуйте задать условие на оценку =5 в колонке «Информатика». Любое условие в
присоединенной таблице отсечет заодно и все пустые ячейки. Напоминаю что, NULL значение не
удовлетворяет ни одной логической операции. Чтобы в отчете остались студенты, которые не
сдавали математику, можно задать «IS EMPTY» в поле «или». Но все равно, из списка из списка
пропадут студенты, получившие другие оценки. Это не ошибка программы, а результат заданного
нами критерия отбора. Не нравится, смело создавайте вспомогательные запросы. Обычно СУБД
их нормально оптимизирует. Кстати, иногда запрос с правым или левым объединением
выполняются даже быстрее, чем запросы с внутренним объединением. Иногда СУБД выбирает
неправильную последовательность выполнения запроса. Использование правого объединения
заставляет СУБД выполнять запрос в другом порядке, в результате, запрос выполняется в
несколько раз быстрее.
Черная кошка в темной комнате
Теперь предположим, что нам нужно найти студентов, которые не сдавали экзамен по
математике. Казалось бы, что проще.
Но результатом такого запроса будет пустой список. Дело в том, что для студентов, не
сдававших экзамен, не просто значение в поле «Оценка» пусто, а вообще нет записи. Трудно
найти черную кошку в темной комнате, особенно если ее там нет.
все комнаты и исключить из списка комнаты где кошка есть.
Для решения нашей задачи надо взять полный список студентов из таблицы «Студент» и
исключить из него студентов, которые имеют оценки. Берем наш запрос «студент - математика» и
задаем для колонки «Математика» критерий «IS EMPTY»
Если таблицы не соединять или «все комбинации»
1…99
Даты
Подсчет статистики
Запросы непосредственно на SQL
Не всегда для решения задач хватает возможностей конструктора запросов. В этом случае
следует нажать кнопку «включить / выключить вид дизайна» и больше, в режим конструктора
запросов не переключаться. Конструктор перестроит ваш запрос, как ему угодно. Открывать такой
запрос следует командой «Редактировать в режиме SQL». Кроме того, SQL запросы, являются
основным способом обращения к базе данных из программ на языках «С», «Pascal», «Java»…
Рассмотрим основные формы запросов:
Запрос
Пояснения
SELECT * FROM "Студент"
Символ «*» означает, что выдаются все поля
таблицы «Студент»
SELECT "Группа", "ФИО", "Дата рождения"
Выбираются только перечисленные поля
FROM "Студент"
SELECT "Группа", "ФИО", "№ зачетки", "Дата
Выбираемые записи сортируются сначала по
рождения" FROM "Студент" ORDER BY "Группа", шифру группы, затем по ФИО (по
"ФИО"
возрастанию).
SELECT "Группа", "ФИО", "№ зачетки", "Дата
Для сортировки по убыванию следует после
рождения" FROM "Студент" ORDER BY "Дата
имени колонки поставить «DESC»
рождения" DESC
SELECT "Группа", "ФИО", "№ зачетки", "Дата
Кроме колонок можно задавать выражения.
рождения", YEAR(NOW()) - YEAR("Дата
При использовании результатов одного запроса
рождения") AS "Возраст" FROM "Студент"
в другом псевдонимы для вычисляемых
ORDER BY "Возраст"
колонок надо задавать обязательно.
Псевдонимы можно использовать при
сортировке и в условиях отбора.
SELECT "Группа", "ФИО", "№ зачетки", "Дата
К сожалению, HSQL не позволяет использовать
рождения", YEAR("Дата рождения") as "Год
псевдонимы в выражениях вычисляемых
рождения", YEAR(NOW()) - YEAR("Дата
колонок. Приходится повторять выражения.
рождения") AS "Возраст" FROM "Студент"
SELECT "Группа", "ФИО", "№ зачетки", "Дата
Условие отбора записей указывается после
рождения", YEAR(NOW( )) - YEAR("Дата
ключевого слова WHERE. Выбираются только
рождения") AS "Возраст" FROM "Студент"
записи, для которых результатом заданного
WHERE "Возраст">20 AND "Группа"='АК1-11'
логического выражения является TRUE.
ORDER BY "Возраст"
SELECT "Группа", "ФИО", "№ зачетки",
Чтобы выбрать записи из нескольких таблиц,
P."Наименование" AS "Предмет" FROM "Студент" надо перечислить их через запятую после
AS S, "Результат" AS R, "Ведомость" AS V,
«FROM». Чтобы меньше писать, используйте
"Предмет" AS P WHERE R."Студент" = S."№
псевдонимы таблиц. Удобнее всего латинские
зачетки" AND R."Ведомость" = V."Код" AND
буквы в верхнем регистре (их можно
V."Предмет" =P."Код"
использовать без кавычек). Но учтите, что если
задали псевдоним таблицы, использовать имя
таблицы в выражениях уже нельзя.
Связи между таблицами в данном примере
задаются условиями:
R."Студент" = S."№ зачетки"
R."Ведомость" = V."Код"
V."Предмет" =P."Код"
SELECT "Группа", "ФИО", AVG("Оценка"+0.0)
FROM "Студент" AS "S", "Результат" AS "R"
WHERE "R"."Студент" = "S"."№ зачетки" GROUP
BY "Группа","ФИО"
При вычислении статистических функций,
колонки, по которым осуществляется
группировка, перечисляются через запятую
после ключевых слов «GROUP BY»
SELECT min("Группа"), min("ФИО"),
AVG("Оценка"+0.0) FROM "Студент" AS "S",
"Результат" AS "R" WHERE "R"."Студент" =
"S"."№ зачетки" GROUP BY "№ зачетки"
Все колонки, перечисленные в SELECT,
должны быть либо перечислены после
«GROUP BY», либо быть статистическими
функциями. В нашем примере каждый студент,
связан только с одной группой, да и
группировать правильнее по номеру зачетки.
Чтобы нам вывести в этом случае шифр группы
воспользуемся, например, функцией min()
SELECT min("Группа"), min("ФИО"),
AVG("Оценка"+0.0) AS "Средний балл" FROM
"Студент" AS "S", "Результат" AS "R" WHERE
"R"."Студент" = "S"."№ зачетки" GROUP BY "№
зачетки" HAVING AVG("Оценка"+0.0)>4.0
Чтобы отобрать записи по итогам подсчета
статистических функций, надо задать условие
после ключевого слова «HAVING». К
сожалению, в HSQL и здесь псевдонимом
воспользоваться не удается. Приходится
повторять выражения.
SELECT "Группа", "ФИО", AVG("Оценка"+0.0)
Не следует ставить после «HAVING» условия
FROM "Студент" AS "S", "Результат" AS "R"
отбора, которые можно задать после WHERE.
WHERE "Группа"='АК1-11' AND "R"."Студент" = Зачем загружать в память данные, и выполнять
"S"."№ зачетки" GROUP BY "Группа","ФИО"
над ними статистические функции, если позже
HAVING AVG("Оценка"+0.0)>4.0
они будут все равно отброшены.
SELECT max("Средний балл") as M FROM
Вместо таблицы можно указать в скобках
(SELECT AVG("Оценка" + 0.0) AS "Средний балл" вспомогательный запрос.
FROM "Результат")
Приведенный пример возвращает
максимальный средний балл из средних баллов
студентов.
SELECT "Группа", "ФИО", AVG("Оценка"+0.0)
Запрос, возвращающий единственное значение
FROM "Студент" AS "S", "Результат" AS "R"
можно использовать в выражениях.
WHERE "Группа"='АК1-11' AND "R"."Студент" = Приведенный пример отбирает студентов со
"S"."№ зачетки" GROUP BY "Группа","ФИО"
средним баллом выше среднего.
HAVING AVG("Оценка"+0.0) > (SELECT AVG(
"Оценка" + 0.0 ) AS "Средний балл" FROM
"Результат")
SELECT "№ зачетки", "Оценка", "Предмет" FROM Поскольку в HSQL не удается непосредственно
"Студент" AS "S" LEFT OUTER JOIN (SELECT
соединить правым соединением три таблицы,
"Студент", "Оценка", "Предмет" FROM "Результат" воспользуемся подзапросом.
AS "R", "Ведомость" AS "V" WHERE
Данный запрос выдает всех студентов и все их
"R"."Ведомость" = "V"."Код" ) AS "B" ON
оценки или NULL, если у студента нет ни
"B"."Студент" = "S"."№ зачетки"
одной оценки.
SELECT
Сохраним предыдущий запрос под именем
S."ФИО", B0."Оценка" AS "Информатика",
"Все студенты-все оценки" и воспользуемся им
B2."Оценка" AS "Компьютерная графика",
для построения запроса с оценками студентов в
B3."Оценка" AS "Математика"
трех колонках
FROM
"Студент" AS S,
"Все студенты-все оценки" AS B0,
"Все студенты-все оценки" AS B2,
"Все студенты-все оценки" AS B3
WHERE
S."№ зачетки"=B0."№ зачетки" AND
(B0."Предмет"=0 OR B0."Предмет" IS NULL)
AND
S."№ зачетки"=B2."№ зачетки" AND
(B2."Предмет"=2 OR B2."Предмет" IS NULL)
AND
S."№ зачетки"=B3."№ зачетки" AND
(B3."Предмет"=2 OR B3."Предмет" IS NULL)
ORDER BY S."ФИО" ASC
Download