|
Программирование >> Построение запросов sql
4. Для вывода выбираются значения полей A.AccountCD и A.Fio из основного запроса (005488, АКСЕНОВ С. А.) и найденное вложенным запросом количество связанных строк в таблице Request (3). 5. Повторяются пп.1-4, пока каждая строка таблицы Abonent не будет просмотрена. Если во внешнем запросе используется предложение GROUP BY, то выражения, указанные в нем, можно использовать внутри подзапросов. Например, с помощью следующего связанного вложенного запроса можно получить общие суммы начислений и оплат по каждому абоненту: SELECT AccountCD, (SELECT Sum (NachislSum) FROM NachislSumma N WHERE N.AccountCD = P.AccountCD) AS Nachisl, Sum (PaySum) AS Pay FROM PaySumma P GROUP BY AccountCD;. Результат выполнения запроса представлен на рис. 3.95.
Рис. 3.95. Результат соотнесенного вложенного запроса Здесь в подзапросе вычисляется общая сумма всех начислений для абонента, отобранного внешним запросом. Затем возвращенное подзапросом значение выводится по каждому абоненту в результирующем столбце Nachisl. Из результата следует, что каждый абонент полностью оплатил начисленные ему суммы. 3.3.2.3.2. Связанные подзапросы в предложениях WHERE и HAVING При использовании связанного вложенного запроса в условиях поиска предложений WHERE и HAVING он может представлять собой <скалярный подзапрос>, <подзапрос столбца> или <табличный подзапрос>, как и для простых вложенных запросов. Однако так как запрос связанный, внутренний запрос выполняется отдельно для каждой строки внешнего запроса (текущая строка-кандидат). Рассмотрим примеры, в которых используются <скалярный подзапрос> и <подзапрос столбца>. Подзапросы, представляющие собой <табличный подзапрос>, будут рассмотрены позднее при изучении предикатов EXISTS и SINGULAR. Например, чтобы вывести все сведения об абонентах, которые подали заявки на ремонт газового оборудования 17 декабря 2001 года, можно использовать следующий связанный вложенный запрос: SELECT * FROM Abonent Out WHERE 17.12.2001 IN (SELECT IncomingDate FROM Request Inn WHERE Out. AccountCD = Inn. AccountCD);. Результат выполнения запроса представлен на рис. 3.96.
Рис. 3.96. Результат связанного вложенного запроса в предложении WHERE В этом примере Out и Inn - это псевдонимы таблиц Abonent и Request соответственно (могут задаваться произвольно). Так как значение в поле AccountCD внешнего запроса меняется (при переборе строк), внутренний запрос должен выполняться отдельно для каждой строки внешнего запроса. В этом примере SQL осуществляет следующую процедуру: 1) выбирает строку c данными об абоненте, имеющем номер лицевого счета 005488 (первая строка) из таблицы Abonent; сохраняет эту строку как текущую строку-кандидат под псевдонимом 2) 3) Out; выполняет вложенный запрос, просматривающий всю таблицу Request, чтобы найти строки, где значение поля Inn.AccountCD - такое же, как значение Out.AccountCD (005488). Затем из каждой такой строки таблицы Request извлекается поле IncomingDate. В результате вложенный запрос, представляющий собой <подзапрос столбца>, формирует набор значений поля IncomingDate для текущей строки-кандидата; после получения набора всех значений поля IncomingDate для поля AccountCD=005488 анализируется условие поиска основного запроса, чтобы проверить, имеется ли значение 17 декабря 2001 в наборе всех значений поля IncomingDate. Если это так (а это так), то выбирается строка с номером лицевого счета 005488 для вывода ее из основного запроса; повторяются пп.1-4 (для строки с номером лицевого счета 015527 и т.д.), пока каждая строка таблицы Abonent не будет проверена. Ту же самую задачу можно решить, используя естественное соединение таблиц Abonent и Request следующим образом: SELECT AccountCD, StreetCD, HouseNO, FlatNO, Fio, Phone FROM Abonent out NATURAL JOIN Request inn WHERE inn.IncomingDate = 17.12.2001;. Результат выполнения будет совпадать с результатом, представленным на рис. 3.96. Однако следует обратить внимание на наличие существенных различий между соединением таблиц и вложенными соотнесенными запросами. Дело в том, что запросы с использованием соединения таблиц формируются СУБД как строки из декартова произведения таблиц, перечисленных в предложении FROM. В случае же с вложенным соотнесенным запросом строки из произведения таблиц не вычисляются благодаря использованию механизма строки-кандидата. Вывод в связанном вложенном запросе формируется в предложении SELECT внешнего запроса, в то время как соединения могут выводить строки из обеих соединяемых таблиц (при указании символа * в предложении SELECT). Но даже если столбцы для вывода при соединении таблиц указаны явно (см. предыдущий пример), то сначала все равно формируется декартово произведение. Каждый SQL-запрос можно оценить с точки зрения используемых ресурсов сервера БД. На практике большинство СУБД подзапросы выполняют более эффективно. Тем не менее, при проектировании комплекса программ с критичными требованиями по быстродействию разработчик должен проанализировать план выполнения SQL-запроса для конкретной СУБД. Тестирование в реальных условиях - единственный надежный способ решить, что лучше работает для конкретных потребностей. Рассмотрим пример сравнения значения, возвращаемого вложенным запросом, с константой. Вывести информацию об исполнителях ремонтных заявок, назначенных на выполнение четырех и более заявок, можно с помощью следующего запроса: SELECT * FROM Executor E WHERE 4<= (SELECT COUNT(R.RequestCD) FROM Request R WHERE E.ExecutorCD = R.ExecutorCD);. Результат выполнения запроса представлен на рис. 3.97.
Рис. 3.97. Результат сравнения вложенного запроса с константой
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |