|
Программирование >> Программирование баз данных
психологический рубеж и научиться рассматривать решаемые задачи комплексно. Не следует думать, что для этого достаточно изучить один-два запроса. Тем не менее, даже если такой подход не удается освоить сразу, часто возникает возможность вначале применить для решения задачи несколько меньших запросов, а затем постепенно соединить их в единый, более крупный запрос, позволяющий непосредственно решить всю задачу. Итак, попытайтесь в первую очередь найти решение задачи в целом, а если этого не удается сделать, не отступайте, разбивайте ее на меньшие подзадачи, а затем снова соединяйте этапы решения в единое целое, продолжая эту работу до тех пор, пока она остается оправданной. По мнению автора, овладение некоторыми темами, представленными в этюй главе, становится значимым рубежом между новичком и профессионалом , если речь идет о программировании для SQL Server. Сказанное не означает, что этим исчерпывается подготовка настоящих сгьеицалихтов, но разработчики, не только агособные заявлять о том, что они знают о существовании усовершенствованных средств формирования запросов и могут применить одну или две конструкции из этюго числа, но действительно сгюсобные сделать с виду неразрешимые запросы разрешимыми, ценятся на вес золота. Я пишу на эти темы для новичков, чтюбы показать им, чтю они выбрали замечательную профессию, и объяснить, чего в ней можно добиться. Я пишу на эти темы для профессионалов, поскольку лишь полное овладение связанными с ними понятиями позволяет достичь наибольших успехов в работе с СУБД SQL Server (а также фактичеаси с любыми ведущими СУБД). В настоящей главе представлен подход, позволяющий находить ответы на многочисленные вопросы с помощью единственного запроса. По существу, в этой главе рассматриваются такие способы выборки данных, для которых на первый взгляд требуется применить несколько запросов, но фактически все необходимые средства обработки данных будут помещены в такую конструкцию, которая будет действовать как единое целое. Написание первоклассных запросов - не самоцель и не стремление создать такую конструкцию, которая окажется максимально сложной; наша задача состоит прежде всего в том, чтобы добиться успешного функционирования запросов. С учетом этого в данной главе будет также рассматриваться тема повышения производительности запросов и будет показано, как добиться от запросов максимальной отдачи. Ниже перечислены темы, которые будут рассматриваться в настоящей главе. Вложенные подзапросы. Связанные подзапросы. Производные таблицы. Использование операции EXISTS. Использование внешних вызовов для выполнения сложных действий. Оптимизация производительности запросов. Кроме того, в этой главе будет показано, как можно с помощью подзапросов решать задачи, которые на первый взгляд кажутся полностью неподдающимися решению, и насколько может измениться производительность запросов из-за небольших корректировок в отдельных конструкциях запросов, которые с вР1ду кажутся незначительными. Общее определение понятия подзапроса Подзапрос- это обычный запрос T-SQL, вложенный в другой запрос с использованием круглых скобок; запросы создаются с помощью оператора SELECT, который служит для выборки определенных данных или является условием другого запроса. Как правило, подзапросы используются для достижения описанных ниже целей. Разбивка запроса на последовательность логических этапов. Составление списка, который вкладывается в конструкцию WHERE с помощью ключевого слова IN, EXISTS, ANY или ALL. Создание поисковой таблицы, соответствующей каждой отдельной строке в родительском запросе. Чаще всего подзапрос можно разработать и создать очень легко, но иногда задача составления подзапроса становится чрезвычайно трудоемкой. Как правило, степень сложности задачи подготовки подзапроса зависит от того, насколько нетривиальной является связь между внутренним запросом (подзапросом) и внешним запросом (главным запросом). Следует также отметить, что вместо большинства операторов с подзапросами (но это определенно не относится ко всем таким операторам) вполне возможно применить операторы с соединениями. Причем в тех случаях, когда действительно можно использовать соединения, именно такой способ организации работы является предпочтительным. Автору однажды пригилось вступить в довольно продолжительный спор со своим сотрудником (при этом в течение нескольких дней произошел обмен почти что тремя десятками пиеем по электронной почте с примерами, доводами и т.д.). Этот спор возник по поводу того, какими сравнительными преимуществами и недостатками обладают соединения и подзапросы. В соответствии с традициями, сложившимися в среде пользователей языка SQL, при любой возможности следует всегда использовать соединения, и я отстаивал именно эту точку зрения (исходя из своего опыта, а не сложившихся традиций; читатель уже, вероятно, заметил, что в некоторых местах данной книги была подчеркнута мысль, что традиционные взгляды могут оказаться ошибочными). С другой стороны, мой сотрудник стремился доказать, что фактически для выполнения подзапросов требуется меньше издержек. В конечном итоге быяо решено проверить обоснованность тех и других утверждений на практике. Как и следовало ожидать, полученные результаты показали, что в различных обстоятельствах становится оправданным либо то, либо другое мнение. Более подробно о том, каковыми являются эти обстоятельства, будет сказано ближе к концу данной главы, после изложения всех необходимых для этого сведений. Итак, после теоретического знакомства с подзапросами, рассмотрим некоторые конкретные типы подзапросов и примеры их применения. Создание вложенного подзапроса Вложенным подзапросом является такой подзапрос, который выполняет исключительно однонаправленное действие- возвращает либо единственное значение, предназначенное для использования во внешнем запросе, либо, возможно, полный список значений, которые предназначены для использования в операции IN. В том случае, если требуется обеспечить осуществление явно заданной операции сравнения на равенство, *= , приходится применять такой подзапрос, который возвращает единственное значение, иными словами, значение одного поля одной строки. Если же предполагается, что подзапрос должен возвратить список значений, то в сочетании с внешним запросом должна использоваться операция IN. Не вдаваясь в подробности, можно отметить, что синтаксическая конструкция запроса с вложенным подзапросом должна выглядеть примерно так, как показано в двух следующих примерах синтаксиса: SELECT <SELECT list> FROM <SomeTable> WHERE <SomeColumn> = ( SELECT <single column> FROM <SomeTable> WHERE <condition that results in only one row returned>) SELECT <SELECT list> FROM <SomeTable> WHERE <SomeColumn> IN ( SELECT <single column> FROM <SomeTable> [WHERE <condition>)] Безусловно, синтаксическая конструкция практически применяемых операторов может выглядеть немного иначе. Это связано не только с тем, что могут изменяться списки выборки и уточняться имена таблиц, но и может быть обусловлено тем, что во внешнем Р1ли внуореннем запросе, а также в обоих запросах может применяться соединение нескольких таблиц. Запросы с вложенными подзапросами, в которых используются операторы select, возвращающие единственные значения Приступим к изучению нюансов использования подзапросов на конкретном примере. Предположим, например, что требуется определить идентификаторы Product ID всех товаров, проданных в первый день после того, как любой товар был куплен в данной торговой системе. Если уже известно, каковым является тот первый день, когда в системе был введен заказ, то проблема не возникает; достаточно применить запрос, который выглядит примерно таким образом: USE AdventureWorks SELECT DISTINCT soh.OrderDate, sod.ProductID FROM Sales.SalesOrderHeader soh JOIN Sales.SalesOrderDetail sod ON soh.SalesOrderlD = sod.SalesOrderlD WHERE OrderDate = 07/01/2001 -- Это - первая дата заказа, OrderDate, в системе
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |