Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Горев “Эффективная работа с СУБД”.pdf
Скачиваний:
208
Добавлен:
28.06.2014
Размер:
4.71 Mб
Скачать

converted to PDF by HupBaH9I

OLE придет нечто более совершенное, но главное, что это не будет шагом назад. OLE Automation - способ управлять и считывать информацию об объектах внешнего по отношению к вашему приложения. Впрочем, разговор об этом чуть ниже.

Следующий способ имеет меньше ограничений. Мы говорим об ODBC (Open Database Connectivity), что можно перевести как Открытый Доступ к Базам Данных. Конечно, ваше приложение должно поддерживать эту технологию. Установив связь с исходной базой данных, далее вы используете набор SQL pass-through функций для выборки, обработки и модификации исходных данных. Наборы этих функций для разных продуктов неодинаковы, но в целом можно говорить о наборе различных реализаций SQL pass-through функций. Изучив их реализацию в одном языке, вы легко можете воспользоваться аналогичной в другом. Теперь вы очень близки к тому, что во внешней базе данных будут отражаться любые изменения, сделанные в таблицах при редактировании данных. Во всяком случае, необходимый инструмент у вас есть. Настоятельно рекомендуем попробовать. Далее мы обязательно обсудим эту технологию более подробно. Скажем прямо, она-то и является краеугольным камнем всей этой книги. В противном случае это была бы уже совсем другая книга.

Теперь поговорим о реализации SQL языка в каждом приложении. Для общения с данными внешнего формата на его родном языке была изобретена технология ODBC. Впрочем, то же самое мы можем сказать и об OLE 2.0. Запутанно? Осталось только набраться терпения. А дальше мы будем говорить о SQL языке.

В наше время только ленивый не пытается программировать. Тем более, что основные операторы любого из языков достаточно просты, что вполне логично. Быстренько набросали схему данных, загнали все в простую плоскую таблицу, запустили Мастер и пошли искать заказчиков. Дальше может быть хуже, а может быть лучше. Поток информации разрастается, одной таблицы мало (при этом кто-то должен подсказать, что данные из разных таблиц можно связывать), и, когда звучит простой вопрос вашего начальника "А сколько африканского кофе мы продали в Тьмутараканскую область по цене между 6000 и 7000 рублей?", - вы берете листок бумаги, счеты (как наиболее надежное средство учета) и ручку. Правильно ли это? Каждая точка зрения имеет право на существование. В том числе и вашего начальника - в вас начинают сомневаться. Но не пугайтесь, у вас в руках наша книга. Почти 90% дела вы сделали, осталось только проявить чуточку усердия и терпеливо дочитать до конца.

Вспомним, что, несмотря на наличие стандарта SQL, существуют различные реализации или диалекты этого языка, которые являются либо вспомогательными инструментами, либо основой различных систем управления базами данных. Есть и более сложные варианты, когда некоторые СУБД имеют специальные библиотеки для доступа к своим данным для таких языков, как C или Visual Basic с помощью SQL команд приложения. В большинстве случаев к данным любого приложения надо обращаться на его родном SQL диалекте. То есть, находясь в среде FoxPro, вам будет сложно сделать запрос SQL к таблице формата Paradox, не используя ODBC и SQL passthrough. Хотя есть приятные исключения, то есть приложения, которые незаметно для вас проводят всю тяжелую работу по представлению чужих данных в нужном для запроса формате.

В самом простом варианте команда, которая выбирает все записи из одной таблицы, выглядит так:

SELECT mytable.* FROM mytable

Впрочем, можно еще короче:

SELECT * FROM mytable

Таким образом, выбраны все записи из таблицы Mytable.

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

Рассмотрим более сложные варианты выбора нужных данных.

Запросы выборки

Начнем с Visual FoxPro. Здесь у нас есть целых три варианта выполнения команд SQL:

1.Набрать команду в окне Command.

2.Создать программу, в которую включить нужную команду. Этот способ более эффективен,

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

3.Способ, наиболее привлекательный для начинающих программистов, - использовать

Relation Query By Example (RQBE) - Реляционный запрос по образцу.

converted to PDF by HupBaH9I

Для того чтобы использовать RQBE, вам достаточно выполнить команду New из меню File, а затем выбрать тип создаваемого файла - Query. RQBE - это интерактивная среда, в которой вы формируете запрос в основном с помощью мыши, перетаскивая нужные вам поля в определенные области диалогового окна.

Результатом будет запрос, оформленный в виде файла с расширением QPR. При этом выполнить запрос вы сможете с помощью команды DO. Если вы изучаете SQL для использования в FoxPro, то пользуйтесь любым из вышеизложенных способов, но если вам нравится RQBE, то все равно заглядывайте в полученный код, потому что это поможет вам лучше понять язык. Разбирайте каждое слово в полученной команде, и успех в недалеком будущем вас будет ожидать всенепременно.

Всреде СУБД Microsoft Access нет командной строки в том понятии, в котором она существует

вVisual FoxPro. Для того чтобы создать запрос, в контейнере БД выберите страницу Запросы, нажмите на кнопку Создать. На экране появится Конструктор запросов. При этом вы легко будете

переходить из Конструктора запросов в окно редактирования SQL или к результатам выполнения запроса.

Среди рассматриваемых средств разработки СУБД Microsoft Access имеет наиболее мощные средства визуального конструирования запросов. Здесь вы можете создать не только запрос на выборку, но и запросы обновления, удаления, создания таблиц, добавления. Об этих запросах мы поговорим ниже.

Visual Basic использует для работы с данными процессор баз данных Microsoft Jet, такой же, как и Access. Но в связи с тем, что Visual Basic является универсальным средством разработки, здесь не присутствуют такие развитые средства визуального проектирования, как в Microsoft Access. В то же время, так как все объекты DAO - объекты по доступу к данных - доступны и из Visual Basic, то мы вполне можем добиться функциональности, которой добиваемся в Access. Другое дело, какой ценой мы этого достигнем.

Напомним, что в Microsoft SQL Server для того, чтобы выполнить команду SQL, необходимо запустить приложение iSQLW. Вы можете набрать требуемую команду и запустить ее на выполнение. При этом на вкладке Query Results вы увидите полученный результат.

Зная SQL, вы можете значительно увеличить ваши возможности при работе с электронными таблицами Microsoft Excel. Несмотря на то, что вы можете непосредственно читать некоторые форматы данных, иногда полезно немного сократить в объеме количество записей перед обработкой в Excel. В этом вам может помочь приложение Microsoft Query, которое можно использовать для построения запросов к данным внешнего и внутреннего формата Excel с целью уменьшения объема данных, необходимых для текущего сеанса работы.

Итак, везде присутствует SQL. Где-то как основное средство работы, где-то как вспомогательное.

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

SELECT * FROM mytable

Заменим абстрактную таблицу Mytable таблицей из примера к этой книге. Одна из таблиц называется Model, в ней хранятся данные о всех моделях автомобилей, которые задействованы в реселлерской деятельности компании. К примеру, нам не нужны для дальнейшей обработки все поля из этой таблицы. Чтобы выбрать нужные, мы должны их просто перечислить:

SELECT name_model, swept_volume, quantity_drum FROM model

Может случиться, что вам захочется иметь более наглядные заголовки вместо часто абстрактных наименований английскими буквами или даже на английском языке. Тогда мы используем ключевое слово AS после названия колонки. Перепишем наш запрос в другом виде:

SELECT name_model AS наименование, ; swept_volume AS рабочий_объем, ; quantity_drum AS кол_цилиндров ; FROM model

Этот синтаксис верен для Visual FoxPro и Microsoft Access. При работе с Microsoft SQL Server

подобная задача выполняется немного по-другому:

SELECT 'наименование'= name_model, : 'рабочий_объем'= swept_volume,; 'кол_цилиндров'= quantity_drum ; FROM model

converted to PDF by HupBaH9I

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

SELECT DISTINCT 'наименование'= name_model, : 'рабочий_объем'= swept_volume,; 'кол_цилиндров'= quantity_drum ;

FROM model

Противоположным по смыслу DISTINCT ключевым словом является ALL, как правило, оно является значением по умолчанию и его можно не приводить. Но это уже зависит от вашего стиля программирования. Иногда считается правильным указывать все значения и ключевые слова для лучшей "читабельности" кода.

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

SELECT name_model, quantity_drum ,swept_volume FROM model

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

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

SELECT IIF(MOD(RECNO(),3)=0,"Y","N"),RECNO(),cost;

FROM "automobile passenger car"

При этом в каждой третьей записи в результирующем курсоре в первой колонке появится буква "Y".

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

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

Если вы хотите узнать, в какой стране находится штаб-квартира фирмы, автомобиль которой приобрел каждый покупатель, то нужно создать вот такой запрос:

SELECT Customer.name_customer, Country.country_name, ; Model.name_model,;

Firm.name_firm;

FROM "auto store!customer", "auto store!account",;

"auto store!automobile passenger car" Automobile_passenger_car,; "auto store!model", "auto store!firm",; "auto store!country";

WHERE Customer.key_customer = Account.key_customer;

AND Automobile_passenger_car.key_auto = Account.key_auto; AND Model.key_model = ; Automobile_passenger_car.key_model;

AND Firm.key_firm = Model.key_firm;

AND Country.key_country = Firm.key_country

В итоге получится следующая выборка:

 

 

 

NAME

COUNTRY

NAME

NAME

_CUSTOMER

 

_MODEL

_FIRM

Безумные медведи

Италия

145 1.4

Alfa Romeo

Общество нац. героев Италия

145 1.4

Alfa Romeo

Пронырливые волки

Италия

146 1.9

Alfa Romeo

Угрюмые слоны

Германия

M3 3.0

BMW

 

 

 

converted to PDF by HupBaH9I

Голодные лисы

Германия

740i 4.0

BMW

Голодные лисы

Германия

840Ci 4.0

BMW

Угрюмые слоны

Германия

840Ci 4.0

BMW

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

Например, строчка

Automobile_passenger_car.key_auto = Account.key_auto

ограничит нашу выборку только теми записями, которые имеют одинаковые значения и в таблице Automobile_passenger_car, и в таблице Account по полю key_auto. Проведя соответствующее исследование для других связующих пар, мы поймем, каким образом ограничивается набор выбранных данных. Вышеприведенный синтаксис правилен для любого диалекта SQL, используемого в рассматриваемых средствах разработки.

Рассмотрим более простой пример. Нам хочется узнать для автомобиля название его фирмы- производителя. Запрос будет выглядеть так:

SELECT model.name_model,firm.name_firm ;

FROM model,firm ;

WHERE model.key_firm = firm.key_firm

Далее рассмотрим, как этот запрос будет выглядеть, если мы построим его с помощью Конструктора запросов Microsoft Access.

SELECT DISTINCTROW firm.name_firm, model.name_model

FROM firm INNER JOIN model ON firm.key_firm = model.key_firm;

В предложении FROM появилась конструкция:

firm INNER JOIN model ON firm.key_firm = model.key_firm

что в дословном переводе означает: внутренняя связь таблицы Firm с таблицей Model по полю key_firm. Почему нельзя просто все записать в предикат, составленный с помощью предложения WHERE? Можно. Но полученный запрос не будет модифицирующим, то есть вы не сможете изменять данные в запросе, а соответственно и редактировать данные в исходной таблице посредством запроса.

Ядро базы данных Microsoft Jet - достаточно гибкое средство в отношении типов и форматов SQL выражений, используемых для создания связей между таблицами. В дополнение к связям, которые вы можете указать в предикате, составляемом с помощью предложения WHERE, Microsoft Jet SQL может использовать предложение JOIN, чтобы указать внутреннюю, левую внешнюю или правую внешнюю связь, а также неэквивалентные связи, в которых связующим критерием является не равенство значений в связующих полях двух таблиц, а выражение условия, которое должно возвращать истину.

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

SELECT DISTINCTROW firm.name_firm, model.name_model, country.country_name

FROM model INNER JOIN (firm INNER JOIN country ON firm.key_country = country.key_country) ON model.key_firm = firm.key_firm ;

В вышеприведенном примере мы ищем штаб-квартиру фирмы-производителя каждой модели. Помимо внутреннего (INNER JOIN) объединения, вы можете использовать внешние

объединения, при этом различаются левые внешние и правые внешние объединения: LEFT JOIN и RIGHT JOIN. Используя левое внешнее объединение, вы получаете в итоговом запросе все записи из левой таблицы и только те записи из правой таблицы, которые имеют соответствующие значения по связующему полю в левой таблице.

SELECT DISTINCTROW [automobile passenger car].date_issue, account.account

converted to PDF by HupBaH9I

FROM [automobile passenger car] LEFT JOIN account ON [automobile passenger car].key_auto = account.key_auto;

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

SELECT DISTINCTROW [automobile passenger car].date_issue, account.account

FROM account LEFT JOIN [automobile passenger car] ON account.key_auto = [automobile passenger car].key_auto;

Microsoft Jet возвращает специальное значение NULL во всех полях для записей внешней таблицы, не содержащих одинаковых значений. Вы можете использовать это свойство для проверки целостности связи в зависимости от присутствия значения типа NULL во внешней таблице. Если в итоговом запросе присутствуют значения типа NULL, вы можете быть уверены в наличии несвязанных записей в дочерней таблице, или, наоборот, есть значения в родительской таблице, для которых отсутствуют соответствующие значения в дочерней таблице. Если вы хотите узнать, с каким поставщиком у вас не было сделок, например, за последний месяц, то лучший и самый быстрый способ это сделать - использовать внешнее объединение.

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

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

SELECT DISTINCTROW firm.name_firm, model.name_model, country.country_name

FROM model INNER JOIN (firm INNER JOIN country ON firm.key_country = country.key_country) ON model.key_firm = firm.key_firm

WHERE country.country_name="Италия" ;

В SQL вы можете использовать логические операторы AND, OR и логическое отрицание NOT. Добавив всего лишь один оператор NOT перед выражением

country.country_name = "Италия"

мы получаем совершенно противоположную выборку, в которой будут присутствовать фирмы всех стран, кроме Италии.

SELECT DISTINCTROW firm.name_firm, model.name_model, country.country_name

FROM model INNER JOIN (firm INNER JOIN country ON firm.key_country = country.key_country) ON model.key_firm = firm.key_firm

WHERE NOT country.country_name="Италия"

При необходимости получить данные для двух стран мы используем оператор OR. Если нам не нужны данные по автомобилям из Франции и Италии, мы используем следующий запрос:

SELECT DISTINCTROW firm.name_firm, model.name_model, country.country_name

FROM model INNER JOIN (firm INNER JOIN country ON firm.key_country = country.key_country) ON model.key_firm = firm.key_firm

WHERE NOT (country.country_name="Италия" OR country.country_name = "Франция")

Вэтом случае необходимо верно расставить скобки, чтобы оператор NOT относился и к Италии

ик Франции.

Пока мы использовали только один оператор сравнения - равно (=), - на самом деле их несколько больше:

>> - больше;

<< - меньше;

>>= - не меньше;

<<= - не больше;

converted to PDF by HupBaH9I

<<>> - не равно.

Еще раз вернемся к предыдущему запросу, оставив прежнюю цель - не выбирать модели из Франции и Италии, но при этом используя совсем другие операторы:

SELECT DISTINCTROW firm.name_firm, model.name_model, country.country_name

FROM model INNER JOIN (firm INNER JOIN country ON firm.key_country = country.key_country) ON model.key_firm = firm.key_firm

WHERE country.country_name<<>>"Италия" AND country.country_name <<>> "Франция"

Обратите внимание, что мы используем AND вместо OR, иначе в итоговом курсоре были бы выбраны все записи.

Операторы сравнения могут обрабатывать не только числовые значения, но и символьные. При этом обрабатывается ASCII-код символа. При необходимости выполнить запрос, в котором мы хотим выбрать страны, названия которых начинаются на букву "И" и последующие буквы в порядке алфавита, мы можем использовать следующие команды:

SELECT DISTINCTROW firm.name_firm, model.name_model, country.country_name

FROM model INNER JOIN (firm INNER JOIN country ON firm.key_country = country.key_country) ON model.key_firm = firm.key_firm

WHERE country.country_name>>="И"

В предикате, который формируется с помощью предложения WHERE, можно и нужно использовать помимо вышеприведенных еще несколько операторов, а именно: IN, BETWEEN, LIKE и IS NULL.

Использование оператора IN позволяет нам по-другому выполнить запрос по выборке данных по Италии и Франции. Вспомните запрос, в котором мы собирали данные для всех стран, кроме Италии и Франции. Теперь мы можем записать его с помощью оператора IN

SELECT DISTINCTROW firm.name_firm, model.name_model, country.country_name

FROM model INNER JOIN (firm INNER JOIN country ON firm.key_country = country.key_country) ON model.key_firm = firm.key_firm

WHERE country.country_name NOT IN ("Италия", "Франция");

Оператор BETWEEN, строго следуя своему дословному переводу, выводит нам данные в промежутке между значениями, которые мы укажем в качестве его аргументов. Если вам нужно выбрать информацию по странам, которые расположены в алфавитном порядке между Италией и Францией, то используйте запрос, подобный нижеприведенному.

SELECT DISTINCTROW firm.name_firm, model.name_model, country.country_name

FROM model INNER JOIN (firm INNER JOIN country ON firm.key_country = country.key_country) ON model.key_firm = firm.key_firm

WHERE country.country_name BETWEEN "Италия" AND "Франция"

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

SELECT DISTINCTROW firm.name_firm, model.name_model, country.country_name

FROM model INNER JOIN (firm INNER JOIN country ON firm.key_country = country.key_country) ON model.key_firm = firm.key_firm

WHERE country.country_name NOT IN ("Италия", "Франция") AND (country.country_name BETWEEN "Италия" AND "Франция")

Оператор LIKE позволяет использовать в критерии поиска шаблоны. Если необходимо выбрать только модели из стран, названия которых начинаются на букву "И", то можно использовать следующий запрос:

SELECT DISTINCTROW firm.name_firm, model.name_model, country.country_name

FROM model INNER JOIN (firm INNER JOIN country ON firm.key_country = country.key_country) ON model.key_firm = firm.key_firm

WHERE country.country_name LIKE "И*'"

converted to PDF by HupBaH9I

И наконец, оператор IS NULL позволяет обнаружить значения типа NULL в указанном поле и соответственно определить, выводить проверенную запись в итоговый курсор или нет. Оператор IS NULL нельзя непосредственно использовать в Visual FoxPro и Microsoft Access. Но в этих языках есть функция ISNULL(). Поэтому можно написать команду следующим образом:

SELECT DISTINCTROW firm.name_firm, model.name_model, country.country_name

FROM model INNER JOIN (firm INNER JOIN country ON firm.key_country = country.key_country) ON model.key_firm = firm.key_firm

WHERE NOT isnull(country.country_name)

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

SELECT DISTINCTROW firm.name_firm, model.name_model, country.country_name

FROM model INNER JOIN (firm INNER JOIN country ON firm.key_country = country.key_country) ON model.key_firm = firm.key_firm

WHERE NOT isnull(country.country_name) ORDER BY firm.name_firm

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

ORDER BY firm.name_firm DESC

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

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

COUNT(*) - возвращает число выбранных записей;

COUNT(ALL Expression) - возвращает количество непустых значений;

COUNT(DISTINCT Expression) - возвращает количество неповторяющихся значений по указанному в Expression выражению;

MAX(Expression) - максимальное значение по указанному выражению;

MIN(Expression) - минимальное значение по указанному выражению;

SUM(ALL/DISTINCT Expression) - сумма по всем или только по неповторяющимся значениям;

AVG(ALL/DISTINCT Expression) - среднее по всем или только по неповторяющимся значениям.

ВMicrosoft Access и Visual FoxPro, в дополнение к вышеприведенным функциям, вы можете вычислить еще и стандартное отклонение, дисперсию и т. д.

Вследующем запросе приводится пример вычисления сумм продаж по конкретным наименованиям автомобилей:

SELECT DISTINCTROW Sum(account.sum) AS Sum_sum, model.name_model

FROM model INNER JOIN (account INNER JOIN [automobile passenger car] ON account.key_auto = [automobile passenger car].key_auto) ON model.key_model = [automobile passenger car].key_model GROUP BY model.name_model

Полученный результат приведен в следующей таблице:

Сумма Наименование

20500

145 1.4

10500

146 1.9

25000

740i 4.0

60000

840Ci 4.0

37000

M3 3.0

converted to PDF by HupBaH9I

Если внимательно посмотреть на текст запроса, то в конце выражения можно увидеть предложение GROUP BY. В стандартном SQL вам просто необходимо группировать запрос по всем выбираемым полям, либо использовать поля как выражения функций агрегирования. Совершенно аналогичные ограничения накладываются на запросы в Microsoft Access. В Visual FoxPro и Microsoft SQL Server таких ограничений нет, и вам не обязательно группировать данные по всем выводимым полям.

При создании запросов перед вами обязательно возникнет необходимость отфильтровать данные по какому-нибудь наименованию. Например, по модели M3 3.0. В принципе, вы можете использовать следующую строку, сформированную с помощью предложения WHERE:

WHERE model.name_model = "M3 3.0"

Но это будет не совсем правильно с точки зрения стандарта SQL. Правильно построенный запрос будет выглядеть следующим образом:

SELECT DISTINCTROW Sum(account.sum) AS Сумм, model.name_model

FROM model INNER JOIN (account INNER JOIN [automobile passenger car] ON account.key_auto = [automobile passenger car].key_auto) ON model.key_model = [automobile passenger car].key_model GROUP BY model.name_model

HAVING model.name_model = "M3 3.0"

Результат этого запроса будет выглядеть следующим образом:

Сумма Наименование

37000

M3 3.0

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

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

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

Подзапросы присоединяются к основному запросу через операторы IN, EXIST, SOME, ANY, ALL. Рассмотрим пример использования оператора IN. Допустим, у нас есть две таблицы с

одинаковой структурой. Необходимо вывести данные из первой таблицы при условии, что по полю kto у выводимых записей нет совпадающих значений.

SELECT kto, skolko FROM first WHERE kto NOT IN ; (SELECT DISTINCT kto FROM second)

Пример использования оператора EXIST. Оператор EXIST - единственный из операторов, не требующий выражения между ключевым словом WHERE и самим собой. Он возвращает истину в зависимости от того, есть ли хоть одна запись в выборке подзапроса. Рассмотрим два решения одной задачи. Нам необходимо выбрать все модели автомобилей, которые стоят больше 25000 и которые мы ухитрились продать хотя бы один раз. Код записан в синтаксисе FoxPro.

SELECT DISTINCT Model.name_model,; Automobile_passenger_car.cost; FROM "auto store!model",;

"auto store!automobile passenger car" ; Automobile_passenger_car ; WHERE Model.key_model = ; Automobile_passenger_car.key_model AND ; Automobile_passenger_car.cost >>=25000 AND Exist ;

(SELECT * FROM account,;

"auto store!automobile passenger car" Automobile_passenger_car ; WHERE account.key_auto = ; Automobile_passenger_car.key_auto)

SELECT DISTINCT Model.name_model, ; Automobile_passenger_car.cost ; FROM "auto store!model",;

"auto store!automobile passenger car" ; Automobile_passenger_car; WHERE Model.key_model = Automobile_passenger_car.key_model AND ; Automobile_passenger_car.cost >>=25000 ;

And Automobile_passenger_car.key_auto NOT IN; (SELECT DISTINCT account.key_auto FROM account)

Соседние файлы в предмете Программирование на Delphi