Программирование >>  Построение запросов sql 

1 ... 42 43 44 [ 45 ] 46 47 48 ... 101


образом, если используется предикат IN, то вложенный запрос выполняется один раз и формирует множество значений, используемых основным запросом. В любой ситуации, где используется реляционная операция сравнения (=), разрешается использовать IN. В отличие от запроса со знаком равенства, запрос с предикатом IN не потерпит неудачу, если больше чем одно значение выбрано вложенным запросом.

Следует отметить, что с помощью предыдущего запроса получены данные об абонентах, которые имеют погашенные ремонтные заявки, но этот запрос не дает информации об абонентах, все заявки которых погашены. Чтобы получить данные об абонентах, все заявки которых погашены, предыдущий запрос можно модифицировать следующим образом: SELECT * FROM Abonent

WHERE AccountCD IN

(SELECT AccountCD FROM Request

WHERE Executed = 1 GROUP BY AccountCD) AND AccountCD NOT IN

(SELECT AccountCD FROM Request

WHERE Executed = 0 GROUP BY AccountCD);.

Результат выполнения этого запроса представлен на рис. 3.87. Абонентов с номерами лицевых счетов 115705 и 080270 нет в результирующей таблице, так как у этих абонентов имеются непогашенные заявки.

ACCOUNTCD

STREETCD

HOUSENO

FLATNO

PHONE

005488

АКСЕНОВ С.А.

556893

443069

СТАРОДУБЦЕВ Е.В.

683014

136160

ШМАКОВ С.В.

982222

136169

ДЕНИСОВА Е.К.

680305

080613

ЛУКАШИНА Р.М.

254417

080047

ШУБИНА Т.П.

257842

Рис. 3.87. Результат выполнения запроса с двумя вложенными запросами

Во вложенном запросе возможно использование той же таблицы, что и в основном запросе. Например, если требуется вывести все данные об абоненте АКСЕНОВ С. А. и обо всех других абонентах, которые проживают с ним на одной улице, то запрос может иметь следующий вид:

SELECT * FROM Abonent

WHERE StreetCD = (SELECT StreetCD FROM Abonent

WHERE Fio=АКСЕНОВ С.А.);.

Результат выполнения запроса представлен на рис. 3.88.



ACCOUNTCD

STREETCD

HOUSENO

FLATNO

PHONE

005488

АКСЕНОВ С.А.

556893

115705

МИЩЕНКО Е.В.

769975

015527

КОНЮХОВ В.С.

761699

Рис. 3.88. Результат использования одной и той же таблицы

В данном примере подзапрос выполняется независимо от внешнего запроса, так как является простым. Сначала будет выполнен вложенный запрос, который выберет значение StreetCD из таблицы Abonent для абонента АКСЕНОВ С.А. Затем основной запрос выберет из той же таблицы Abonent строки со значением поля StreetCD, равным значению, выбранному вложенным запросом.

Во вложенном запросе можно использовать агрегатные функции. Допустим, необходимо вывести абонентов и значения их начислений за 2001 год, превышающие среднюю сумму начислений по всем абонентам за этот год. Запрос будет иметь следующий вид:

SELECT AccountCD, NachislSum, NachislMonth, NachislYear,

(SELECT AVG(NachislSum)

FROM NachislSumma

GROUP BY NachislYear

HAVING NachislYear=2001) AS Avg All

FROM NachislSumma

WHERE NachislSum > (SELECT AVG(NachislSum)

FROM NachislSumma GROUP BY NachislYear HAVING NachislYear=2001)

AND NachislYear=2001 ORDER BY 1;.

Результат выполнения запроса представлен на рис. 3.89.

ACCOUNTCD

NACHISLSUM

NACHISLMONTH

NACHISLYEAR

AVG ALL

005488

58,70

2001

58,17

080047

80,00

2001

58,17

080270

60,10

2001

58,17

115705

250,00

2001

58,17

115705

58,70

2001

58,17

136169

58,70

2001

58,17

443069

80,00

2001

58,17

Рис. 3.89. Результат использования одной и той же таблицы

В этом примере вложенный запрос выполняется один раз, возвращая среднее значение поля NachislSum за 2001 год. Затем это значение последовательно сравнивается с каждой выбираемой строкой из таблицы NachislSumma. Рассмотрим еще два примера. Для вывода погашенных ремонтных заявок с наиболее поздней датой поступления можно, используя следующий запрос:



SELECT * FROM Request

WHERE IncomingDate = (SELECT MAX (IncomingDate)

FROM Request

WHERE Executed=1);.

Результат выполнения запроса представлен на рис. 3.90.

REQUESTCD

ACCOUNTCD

EXECUTORCD

FAILURECD

INCOMINGDATE

EXECUTIONDATE

EXECUTED

005488

17.12.2001

20.12.2001

080270

17.12.2001

27.12.2001

Рис. 3.90. Результат использования агрегатной функции

Для вывода абонентов с наибольшими значениями оплаты можно использовать следующий запрос:

SELECT Abonent.Fio, PaySumma.* FROM PaySumma, Abonent

WHERE PaySum = (SELECT MAX(PaySum) FROM PaySumma)

AND Abonent.AccountCD = PaySumma.AccountCD;.

Результат выполнения запроса представлен на рис. 3.91.

PAYFACTCD

ACCOUNTCD

GAZSERVICECD

PAYSUM

PAYDATE

PAYMONTH

PAYYEAR

МИЩЕНКО Е.В.

115705

250,00

03.10.2001

2001

МИЩЕНКО Е.В.

115705

250,00

06.10.2000

2000

Рис. 3.91. Результат выполнения запроса

Вложенные запросы можно применять в предложении HAVING. Они могут использовать свои собственные агрегатные функции (если эти функции не возвращают многочисленных значений). Также в подзапросе, включенном в условие поиска предложения HAVING внешнего запроса, могут использоваться свои собственные предложения GROUP BY и HAVING. Следует помнить, что аргументы, указанные в HAVING, должны присутствовать в качестве аргументов и в GROUP BY.

Например, для подсчёта числа абонентов с максимальными значениями оплаты за 2000 год можно использовать следующий запрос:

SELECT COUNT(DISTINCT AccountCD), PaySum

FROM PaySumma

GROUP BY PaySum

HAVING PaySum = (SELECT MAX(PaySum)

FROM PaySumma WHERE PayYear = 2000);.

Результат выполнения запроса представлен на рис. 3.92.

COUNT

PAYSUM

250,00

Рис. 3.92. Результат вложенного запроса в предложении HAVING



1 ... 42 43 44 [ 45 ] 46 47 48 ... 101

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика