Программирование баз данных MS SQL Server (1084479), страница 66
Текст из файла (страница 66)
Именно с этого момента начинаются сложности. Если бы применялся вложенный подзапрос, то с его помощью происходил бы поиск только самого первого значения даты во всей таблице, а теперь мы должны узнать, каковой была дата поступления первого заказа от каждого отдельного заказчика. В этом не было бы ничего сложного, если бы допускалось использование двух отдельных запросов, поскольку достаточно было бы просто создать времени)чо таблицу, а затем выполнить операцию соединения с этой таблицей. Временная таблица полностью соответствует своему названию.
Таковой является таблица, кото))ая создается для в))сменного использование, а посев завершения соответствующего этапа обработки данных уничтожается. В этом отношении временные таблиць) полностью аналогичны пе))змеиным. Описание ву)еменних таблиц вьсходит за )замки настоящей главь), но в следухпцих главах мы еще будем возвращаться к теме временных таблиц. Решение, основанное на использовании временной таблицы, может выглядеть примерно таким образом: ПЕЕ Ногсьнтпа — Получить список заказчиков и определить ллн каждого дату первого заказа ЕЕЬЕСТ Сцзс ег10, МТН((огбе васе)) АВ ОгбегОасе 1КТО $мтпогбегОасез ЕЬОМ О бе СВОПР Вг Сцзсопег10 ОВОЕВ ВУ Сцзсоиег10 -- Выполнить необходимые дополнительные действия с этой информацией ЗЕЬЕСТ о.С Г ег10, о.огбег10, о.о аегОасе ЕВОЕ Огбегз о 801М ()М1погс)егбасез Г ОМ о.сцзсопег10 = Г.сцзсопег10 АМО о.о с(егОасе = Г.огс)егОасе ОБРЕК ВУ о.сцзсоыег10 ОПОР ТАВОЕ ем1погбегРасез Выполнение этих операторов приводит к получению 89 строк, как показано ниже.
(89 ГОн(Э) агтЕСГЕО) 260 Глава 7 О»да 10 О»Па»Оасе Саясовег10 1997-08-25 00:00:00.000 1996-09-18 00:00:00.000 1996-11-27 00:00:00.000 1996-11-15 00:00:00.000 1996-08-12 00:00:00.000 10643 10308 10365 10355 10278 АЬГК1 АМАТЕ АНТОН АРООТ НЕКОЕ 1996-07-31 00:00:00.000 1997-07-30 00:00:00.000 1996-12-05 00:00:00.000 10269 10615 10374 ИН1ТС И1ЬМК ИОЬЕА (89 гои(я) аггессеа) Как уже бьыо сказано, п~и выполнении того же сцена()ии на компьютере читателя могут быть получены результаты, отличные от приведенны» в этом примере. Пфичина этого мо- жет быть связана с тем, что вы ИРовели с данными базы данных Могг)7 ндпг) либо больше, либо меньше экспериментов, чем автф. 8ЕЬЕСТ о1.сяяяовег10, о1.0»с(ег10, о1.0»с)егОасе ГНОМ Огс(егя о1 ИНКНК о1.0»аагОасе = (ЕКЬКСт М1п(о2.окая»пасе) ГРОМ Огс)егя о2 ИНЕНЕ о2.саяьове»10 = о1.саяьоваг10) ОНОКН Вт Саяяовегкп Применение этого оператора приводит к получению тех же 89 строк: Огае»Оаье Огс)е»10 Саяьовег10 1997-08-25 00:00:00.000 1996-09-18 00:00:00.000 10643 10308 АЬГК1 Аилтн Итак, в данном случае формируются два полностью отдельных результирующих набора.
На это указывает тот факт, что в результатах присутствуют две разные строки с указанием количества затронутых строк, гои (я] аТТессес(. Но такая организация работы чаще всего отрицательно влияет на производительность. Этот вопрос будет рассматриваться более подробно в данной главе после описания других способов решения данной задачи. Однако следует отметить, что иногда такой подход, основанный на использовании двух запросов, становится единственным способом добиться поставленной цели без применения курсора, но рассматриваемая задача не относится к такой категории. Итак, было бы желательно объединить два приведенных выше запроса в один, но для этого необходимо найти способ поиска информации о каждом отдельном заказчике.
Этой цели можно достичь, используя внутренний запрос, который выполняет поиск с учетом текущего значения Спягове»10, полученного из внешнего запроса. После этого необходимо снова вернуть результат внутреннего запроса во внешний запрос, чтобы можно было выполнить выборку требуемых строк по данным о самой ранней дате заказа. Оператор, созданный на основании изложенных требований, может выглядеть примерно так: Дополнительные сведения о запросах 261 10365 10355 10278 1996-11-27 00:00:00.000 1996-11-15 00:00:00.000 1996-08-12 00:00:00.000 китон АНОСТ ВКНСБ 1996-07-31 00:00:00.000 1997-07-30 00:00:00.000 1996-12-05 00:00:00.000 ИН1ТС 10269 ИТЬИК 10615 ХОьеа 10374 (89 гон(з) аггессес) В этом запросе заслуживают внимания несколько описанных ниже важных особенностей.
(3 В результатах обнаруживается только одно сообщение о количестве затронутых строк, гон(з) абгесгео. На этом основании можно с уверенностью сказать, что для выполнения был намечен только один план запроса. (3 Внешний запрос (в данном примере) весьма напоминает по внешнему виду вложенный подзапрос, а внутренний запрос имеет явно определенную ссылку на внешний запрос (обратите внимание на использование псевдонима "о1"). 63 Псевдонимы применяются в обоих запросах (дюке несмотря на то, что на первый взгляд во внешнем запросе псевдоним не требуется), поскольку псевдонимы необходимы для каждого явного обращения к столбцу из внешнего или внутреннего запроса (при этом либо внутренний запрос обращается к столбцу внешнего запроса, либо наоборот).
Обычно у)пя'иачинЕЮЩИК,'-рвзрвботч))ков"~теновитсв'зивхЧитйлввмм' иотсчнИ),КОМ,ПутесниЦы йебледийй-йуиктткйсйюлйийсл иеббкрдимббти',использсйвтй-поевдбнуимы',''.нр истине'йвТ КЛЮьЧВЕТСЛ,.ВТТОМ',-,Чт(О "ПоввдСИИМЫ,ИНОГдв''двйСТВИтв))ЬИСИ)М(ИЫ",-ЕЗ()йОГда)нвт;,"Аестср-'ОбмгЧИр НЕ,':ИСПОЛЬрОВая)ПСЕВДОНИМЫ "ВО; ЕСЕХ-'тИПбех'-:Ежл'ВКЕНИЫК)лсдЗВПроорв';,КОтОрмчЕ;рабрМВтрИ- велись'.в:Йачвльий)(Реа((влек,зуба; главы; е;:что(кйсйетф'= свйзбййык йрйаепрссб~ -то)е иим .йеизь)йии(улримфийюгтсл',: псее)(бйим))(.
'существует', йй)(ежире,и(п))к)стбепрейило'.—".,:-,'псевдрий(м.иербходиыо'предусметриватьдлй Лабай-:т)абЛИцм',,(И" ОСТНОоясщИКСя, Кз йай:-'СтОЛбцсе),'ИЕ''КЬтюрун дбЛЗ(ЧВ:бйтйофОр~амрс)ЕВНа; ссылкв'=,из; внешнрго запроСв 'Но''прсоблема';ееключеетсй в том,'='.что йри пойытксе)сосгтсввитбьб 'Звлсртре руКОВОдотеуяСЬ, ЗтИМ'.йрВВИЛОМ';",МО)гКЕт;ОЧЕзнв';бЫОГрТО ВОЗНИКИ))тЬ)лутаНИ(ЗВ В;Отй()у ')ЛЕНйИ'тОГО;:дйи,'ЧЕГО': (у)КЕИ:Повей()НИМ;;(ЕдсЛя'ЧЕГО'НЕт.'',В(рМО)йу)Рйкизй ОРРВВ4аИИЫйт(СДКОД ссстсйт е:том;:.чтМып~йдус)йатриватипб)вело)(имь( т)лл))оех таблиц; Втопозеоллет„увереиу НО рВЗбИратЬС»:В тсы;-йЗ КЕКОВ твбЛИцб(кавс)ту Звлсржал()от) ПВЕТИСКОМВЛ,'ИНОГО)ЗМВСВ)я: В рассматриваемом примере сообщение 89 сои(э) аггессес( появилось только один раз.
Это связано с тем, что в запросе 89 строк действительно были затронуты только единожды. Даже на основании только этого наблюдения можно сделать вывод, что последняя версия с одним запросом должна, по-видимому, обладать более высоким быстродействием, чем версия с двумя запросами. Так оно и обстоит в действительности. Дополнительная информация на эту тему также будет приведена ниже. 262 Глава 7 В данном конкретном запросе внешний запрос ссылается на внутренний запрос в конструкции ХНЕНЕ.
Во внешнем запросе реализована также возможность запросить данные из внутреннего запроса для включения в список выборки. При обычных обстоятельствах право использовать или не использовать псевдоним остается за разработчиком, а когда речь идет о связанных подзапросах, применение псевдонимов часто становится обязательным. Данный конкретный запрос представляет собой весьма наглядный пример, показывающий, чем обусловлена такая необходимость, поскольку в нем и внутренний, и внешний запросы основаны на одной н той же таблице.
Очевидно, что оба запроса получают информацию друг от друга, поэтому без псевдонимов невозможно было бы указать, какой экземпляр данных таблицы представляет интерес в том и в другом случае. Применение связанных подзапросов в списке выборки Результаты выполнения этого запроса приведены ниже. Соврапунаве Огоег Вате 1997-08-25 00:00:00.000 1996-09-18 00:00:00.000 1996-11-27 00:00:00.000 1996-11-15 00:00:00.000 1996-08-12 00:00:00.000 1997-04-09 00:00:00.000 А1тгеоя Гпттегхьяте Апа Тгп7111о Еврагесасоя у Ье1апоя Аптопьо Могепо ТаЧпет1а Агоппо Гпе Ного Вегд1ппоя япаЬЬКор 81апет эее Ре11хатеяяеп Подзапросы могут также использоваться для получения в виде результатов выборки ответов немного другого рода. Необходимость в этом часто возникает, если искомая информация принципиально отличается по своему составу от остальной части данных, рассматриваемых в запросе (например, если необходимо выполнить агрегирование данных по одному столбцу, но желательно при этом избежать влияния выполнения операции агрегирования на результаты выборки данных из других столбцов).
В качестве примера подзапроса такого типа рассмотрим немного модифицированную версию запроса, который использовался в последнем разделе. Но в данном случае требуется определить только имена заказчиков и первую дату получения заказа от каждого из заказчиков. Для составления требуемого запроса придется внести более значительные изменения, чем может показаться на первый взгляд. Прежде всего, теперь в результатах должно присутствовать имя заказчика, а это означает, что в запрос необходимо включить таблицу спясовегя. Кроме того, больше не требуется включать в запрос какое- либо условие, поскольку должны быть получены данные по всем заказчикам (без исключения), и требуется лишь узнать, какова дата получения первого заказа от этих заказчиков. Фактически применение связанного подзапроса позволяет составить немного более простой запрос, чем тот, который использовался перед этим для решения уклзэнной задачи. Новый вариант запроса выглядит следующим образом: ЯЕЬЕСТ сп.Соврапунаве, (ЯЕЬЕСТ М1п(огпегпате1 ГНОМ Огоегя о ХНЕНЕ о.спятовег10 = сп.сиятовег10) Ая "Огоег Расе" ГНОМ Соятовегя сп дополнительные сведения о запросах ввбЗ 1996-07-31 00:00:00.000 1997-07-30 00".00:00.000 1996-12-05 00:00:00.000 Хььсе С1очег Магхеся ХЬ1вап Ка1я Хп1як1 Ея3ягп' (91 гон(я) аТТяссег() Обработка данных, содержащих МОЫ~-значения, с помощью функции ~8ытп.ь В действительности количество функций, специально предназначенных для обработки данных, содержащих Уч(Л.(: значения, невелико, но в рассматриваемой ситуации мы имеем возможность воспользоваться чрезвычайно полезной функцией такого типа — 1БМОЬЬ () .