Мартин Грубер - Понимание SQL (991940), страница 22
Текст из файла (страница 22)
Теперь Вы начинаете понимать, сколько способов имеется в SQL. Если это все кажется несколько путаннымна этой стадии, нет причины волноваться. Вы обучаетесь, чтобы использовать ту технику, которая лучше всего отвечает вашим требованиям и наиболее понятна для вас.Начиная с этого места, мы хотим показать Вам большое количество возможностей,что бы вы могли найти ваш собственный стиль.=============== SQL Execution Log ============| SELECT *|| FROM Customers outer|| WHERE 1 >|| (SELECT COUNT (*)|| FROM Customers inner|| WHERE outer.rating <= inner.rating|| AND inner.city = 'Rome');|| ============================================= ||cnumcnamecityratingsnum|| -------------------- ------ ||2004GrassBerlin3001002 ||2008CisnerosSan Jose3001007 |===============================================Рисунок 13.13: Использование COUNT вместо EXISTSРЕЗЮМЕИтак, вы прошли много чего в этой главе.
Подзапросы не простая тема, и мы потратили много время чтобы показать их разновидности и неоднозначности. То чемуВы теперь научились, вещи достаточно глубокие. Вы знаете несколько техническихрешений одной проблемы, и поэтому вы можете выбрать то которое более подходитвашим целям. Кроме того, вы поняли, как различные формулировки будут обрабатывать пустые значения (NULL) и ошибки.Теперь, когда вы полностью изучили запросы, наиболее важный, и вероятнонаиболее сложный, аспект SQL, объем другого материала будет относительно простдля понимания.Мы имеем еще одну главу о запросах, которая покажет вам как объединить выводы любого числа запросов в единое тело, с помощью формирования объединениямногочисленых запросов используя оператор UNION.РАБОТА С SQL1.
Напишите запрос, который бы выбирал всех заказчиков чьи оценки равны илибольше чем любая (ANY) оценка заказчика Serres.2. Что будет выведено вышеупомянутой командой?3. Напишите запрос, использующий ANY или ALL, который бы находил всехпродавцов, которые не имеют никаких заказчиков, размещенных в их городе.4.
Напишите запрос, который бы выбирал все порядки с суммой больше чем любая (вобычном смысле) для заказчиков в Лондоне.5. Напишите предыдущий запрос с использованием MAX.(См. Приложение A для ответов.)14ИСПОЛЬЗОВАНИЕПРЕДЛОЖЕНИЯ UNIONВ ПРЕДШЕСТВУЮЩИХ ГЛАВАХ МЫ ОБСУЖДАЛИ различные способы, которыми запросы могут помещаться один внутрь другого. Имеется другой способ объединения многочисленых запросов — т.е. формирование их в объединение. В этой главевы научитесь использованию предложения UNION в SQL. UNION отличается от подзапросов тем что в нем ни один из двух (или больше) запросов не управляются другимзапросом. Все запросы выполняются независимо друг от друга, а уже вывод их —обьединяется.ОБЪЕДИНЕНИЕ МНОГОЧИСЛЕННЫХ ЗАПРОСОВ В ОДИНВы можете поместить многочисленые запросы вместе и объединить их вывод,используя предложение UNION.
Предложение UNION обьединяет вывод двух или более SQL запросов в единый набор строк и столбцов. Например, чтобы получить всехпродавцов и заказчиков размещенных в Лондоне и вывести их как единое целое вымогли бы ввести:SELECT snum, snameFROM SalespeopleWHERE city = 'London'UNIONSELECT cnum, cnameFROM CustomersWHERE city = 'London';и получить вывод показанный в Рисунке 14.1.Как вы можете видеть, столбцы выбранные двумя командами выведены так, какесли она была одна. Заголовки столбца исключены, потому что ни один из столбцоввыведенных объединением, не был извлечен непосредственно из только одной таблицы.
Следовательно все эти столбцы вывода не имеют никаких имен (смотрите Главу 7, обсуждающую вывод столбцов).Кроме того обратите внимание, что только последний запрос заканчивается точкой с запятой. Отсутствие точки с запятой дает понять SQL, что имеется еще одно илиболее запросов.=============== SQL Execution Log ============||| SELECT snum, sname|| FROM Salespeople|| WHERE city = 'London'|| UNION|| SELECT cnum, cname|| FROM Customers|| WHERE city = 'London';|| ============================================= |||| -----------||1001Peel||1004Motika||2001Hoffman||2006Climens|||===============================================Рисунок 14.1: Формирование объединения из двух запросовКОГДА ВЫ МОЖЕТЕ ДЕЛАТЬ ОБЪЕДИНЕНИЕ МЕЖДУЗАПРОСАМИ?Когда два (или более) запроса подвергаются объединению, их столбцы выводадолжны быть совместимы для объединения.
Это означает, что каждый запрос долженуказывать одинаковое число столбцов и в том же порядке что и первый, второй, третий, и так далее, и каждый должен иметь тип, совместимый с каждым. Значение совместимости типов — меняется. ANSI следит за этим очень строго и поэтомучисловые поля должны иметь одинаковый числовой тип и размер, хотя некоторыеимена используемые ANSI для этих типов являются синонимами. (Смотрите Приложение B для подробностей об ANSI числовых типах.) Кроме того, символьные полядолжны иметь одинаковое число символов (значение предназначенного номера, необязательно такое же как используемый номер).Хорошо, что некоторые SQL программы обладают большей гибкостью, чем этоопределяется ANSI.
Типы не определенные ANSI, такие как DATA и BINARY, обычнодолжны совпадать с другими столбцами такого же нестандартного типа.Длина строки также может стать проблемой. Большинство программ разрешаютполя переменной длины, но они не обязательно будут использоваться с UNION. Сдругой стороны, некоторые программы (и ANSI тоже) требуют чтобы символьные полябыли точно равной длины. В этих вопросах вы должны проконсультироваться с документацией вашей собственной программы.Другое ограничение на совместимость — это когда пустые значения (NULL) запрещены в любом столбце объединения, причем эти значения необходимо запретитьи для всех соответствующих столбцов в других запросах объединения.
Пустые значения (NULL) запрещены с ограничением NOT NULL, которое будет обсуждаться в Главе18. Кроме того, вы не можете использовать UNION в подзапросах, а также не можетеиспользовать агрегатные функции в предложении SELECT запроса в объединении.(Большинство программ пренебрегают этими ограничениями.)UNION И УСТРАНЕНИЕ ДУБЛИКАТОВUNION будет автоматически исключать дубликаты строк из вывода.
Это нечтонесвойственное для SQL, так как одиночные запросы обычно содержат DISTINCT чтобы устранять дубликаты. Например запрос, чей вывод показывается в Рисунке 14.2,SELECT snum, cityFROM Customers;имеет двойную комбинацию значений (snum=1001, city=London), потому что мы неуказали, чтобы SQL устранил дубликаты. Однако, если мы используем UNION в комбинации этого запроса с ему подобным в таблице Продавцов, то эта избыточная комбинация будет устранена. Рисунок 14.3 показывает вывод следующего запроса.SELECT snum, cityFROM CustomersUNIONSELECT snum, cityFROM Salespeople.;=============== SQL Execution Log ============| SELECT snum, city|| FROM Customers;|| ============================================= || snumcity|| -----------||1001London||1003Rome||1002San Jose||1002Berlin||1001London||1004Rome||1007San Jose|===============================================Рисунок 14.2: Одиночный запрос с дублированным выводом=============== SQL Execution Log ============| FROM Customers|| UNION|| SELECT snum, sity|| FROM Salespeople;|| ============================================= |||| -----------||1001London||1002Berlin||1007San Jose||1007New York||1003Rome||1001London||1003Rome||1002Barcelona||1007San Jose|===============================================Рисунок 14.3: UNION устраняет двойной выводВы можете получить нечто похожее (в некоторых программах SQL, используяUNION ALL вместо просто UNION, наподобии этого:SELECT snum, cityFROM CustomersUNION ALLSELECT snum, cityFROM Salespeople;ИСПОЛЬЗОВАНИЕ СТРОК И ВЫРАЖЕНИЙ С UNIONИногда, вы можете вставлять константы и выражения в предложения SELECTиспользуемые с UNION.
Это не следует строго указаниям ANSI, но это полезная и необычно используемая возможность. Константы и выражения которые вы используете,должны встречать совместимые стандарты которые мы выделяли ранее. Эта свойство полезно, например, чтобы устанавливать комментарии указывающие какой запросвывел данную строку.Предположим что вы должны сделать отчет о том, какие продавцы производятнаибольшие и наименьшие порядки по датам.
Мы можем объединить два запроса,вставив туда текст чтобы различать вывод для каждого из них.SELECT a.snum, sname, onum, 'Highest on', odateFROM Salespeople a, Orders bWHERE a.snum = b.snum AND b.amt = ( SELECT MAX (amt)FROM Orders cWHERE c.odate = b.odate )UNIONSELECT a.snum, (sname, (onum ' Lowest on', odateFROM ( Salespeople a, Orders bWHERE a.snum = b.snum AND b.amt = ( SELECT MIN (amt)FROM Orders cWHERE c.odate = b.odate );Вывод из этой команды показывается в Рисунке 14.4.Мы должны были добавить дополнительный пробел в строку 'Lowest on', чтобысделать ее совпадающей по длине со строкой 'Highest on'.
Обратите внимание чтоPeel выбран при наличии и самого высокого и самого низкого (фактически он единственый) порядка на 5 Октября. Так как вставляемые строки двух этих запросов различны, строки не будут устранены как дубликаты.=============== SQL Execution Log ============| AND b.amt =|| ( SELECT min (amt)|| FROM Orders c|| WHERE c.odate = b.odate);|| ============================================= |||| ----- ------- ------ ---------- ----------- || 1001 Peel3008Highest on 10/05/1990 || 1001 Peel3008Lowest on 10/05/1990 || 1001 Peel3011Highest on 10/06/1990 || 1002 Serres3005Highest on 10/03/1990 || 1002 Serres3007Lowest on 10/04/1990 || 1002 Serres3010Lowest on 10/06/1990 || 1003 Axelrod 3009Highest on 10/04/1990 || 1007 Rifkin3001Lowest on 10/03/1990 |===============================================Рисунок 14.4: Выбор наивысших и наинизших порядков, определяемых с помощью строкИСПОЛЬЗОВАНИЕ UNION С ORDER BYДо сих пор, мы не оговаривали, что данные многочисленых запросов будут выводиться в каком то особом порядке.