|
Программирование >> Разработка пользовательского интерфейса
И наконец, оператор 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 выражению; MAK(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 Если внимательно посмотреть на текст запроса, то в конце выражения можно увидеть предложение 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) Возможно, вы найдете еще более короткое решение данной задачи, не корите нас, так как мы думаем еще и об учебных целях приводимых примеров. В первом решении с помощью оператора EXIST мы просто проверяем таблицу Account на наличие записей во внутреннем подзапросе. Во втором решении нас интересует просто список значений, которые у нас имеются, после выполнения внутреннего запроса по полю key auto. Второе решение дает правильный ответ, а первое неправильный. Почему? Обратимся к теории. Внутренний запрос выполняется только один раз, и внешний запрос при своей работе обращается только к его итогу, раз за разом проходя по всем записям. Естественно, что оператор EXIST здесь оказывается совершенно бесполезным. Есть ли выход из положения? Безусловно. Согласно теории, если мы свяжем внешний и внутренний запрос, получив при этом связанный подзапрос, то вынудим внешний запрос обращаться к внутреннему каждый раз во время обработки записей при решении, выводить ли выбранные поля в итоговый курсор. Поэтому мы выводим во внешнем запросе еще одно поле Automobile passenger car.key auto и связываем внешний и внутренний запрос по этому полю. Теперь правильный запрос с использованием оператора EXIST выглядит так: SELECT Model.name model, ; Automobile passenger car.cost, ; Automobile passenger car.key auto; 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 WHERE ; Automobile passenger car. key auto=account.key auto) Не надо после всех вышеприведенных манипуляций пессимистически относиться к оператору EXIST. Ведь теперь мы получили внутренний подзапрос в полное управление и можем развить свой запрос еще больше, помня о том, что его результат будет пересматриваться раз за разом после обработки очередной записи во внешнем запросе. Пример использования операторов ANY и SOME. Использование операторов ANY и SOME приводит к совершенно одинаковым результатам. В качестве примера решим предыдущую задачу: SELECT 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= ; ANY (SELECT DISTINCT account.key auto FROM account); Пример использования операторов ALL. Оператор ALL используется с операторами сравнения >> и << и подзапросом. Оператор ALL с оператором >> перед ним означает, что сравниваемое значение должно быть больше любого значения в списке значений, полученных в подзапросе. В противоположном случае - соответственно меньше любого значения в списке. SELECT 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 >>=ALL ; (SELECT DISTINCT summa FROM account ; WHERE summa>>=30000) Запросы добавления Не стоит особо пропагандировать необходимость добавления записей в таблицы в системах обработки данных. Они ведь и становятся настоящими таблицами, когда в них появляются записи. За этот процесс в языке SQL отвечает команда INSERT. Она имеет два варианта использования. В первом случае вы добавляете одну запись с конкретными данными в конкретные поля. Во втором случае вы можете добавить одну и более записей, набор которых формируется запросом. Необходимо отметить, что второй вариант синтаксиса не реализован в версии Visual FoxPro 3.0. Тем не менее его легко реализовать в два шага. Рассмотрим конкретные примеры. В таблицу Account добавим одну запись:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |