Книга: Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ
Улучшенные условия группирования
Разделы на этой странице:
Улучшенные условия группирования
Firebird 1.5 и более поздние версии поддерживают некоторые дополнительные условия группирования, недоступные в версии 1.0.x.
Подзапросы во встроенных агрегатах
Группируемое поле, которое связано с выражением подзапроса, может содержать агрегатное выражение, ссылающееся на элемент агрегатного выражения в списке
GROUP BY.
В следующем примере реентерабельный подзапрос к системной таблице RDB$RELATION_FIELDS содержит агрегатное выражение (MAX(I:.RDB$FIELD_POSITION)), результат которого используется для локализации имени (RDB$FIELD_NAME) столбца, имеющего наибольший номер позиции для каждой таблицы (RDB$RELATION_NAME) в базе данных:
SELECT
r.RDB$RELATION_NAME,
MAX(r.RDB$FIELD_POSITION) AS MAXFIELDPOS,
(SELECT
r2,RDB$FIELD_NAME FROM RDB$RELATION_FIELDS r2
WHERE
r2.RDB$RELATION _NAME = r.RDB$RELATION_NAME
and r2.RDB$FIELD_POSITION = MAX(r.RDB$FIELD_POSITION)) AS FIELDNAME
FROM RDB$RELATI ON_FIELDS r
/* мы используем предложение WHERE для фильтрации системных таблиц */
WHERE r,RDB$RELATION NAME NOT STARTING WITH 'RDB$'
GROUP BY 1;
RDB$RELATION_NAME |
MAXFIELDPOS |
FIELDNAME |
=========== |
============ |
========= |
COUNTRY |
1 |
CURRENCY |
CROSS_RATE |
3 |
UPDATE_DATE |
CUSTOMER |
11 |
ON_HOLD |
DEPARTMENT |
6 |
PHONE_NO |
EMPLOYEE |
10 |
FOLL_NAME |
EMPLOYEE_PROJECT |
1 |
PROJ_ID |
JOB |
7 |
LANGUAGE_REQ |
PHONE_LIST |
5 |
PHONE_NO |
PROJECT |
4 |
PRODUCT |
PROJ_DEPT_BUDGET |
4 |
PROJECTED_BUDGET |
SALARY_HISTORY |
5 |
NEW_SALARY |
SALES |
12 |
AGED |
Теперь в тех же самых текстах мы используем COUNT() для подсчета количества столбцов, хранимых в каждой таблице:
SELECT
rf.RDB$RELATION_NAME AS "Table Name", (
SELECT
r.RDB$RELATION_ID
FROM RDB$RELATIONS r
WHERE r.RDB$RELATION_NAME = rf.RDB$RELATION_NAME) AS ID,
COUNT(*) AS "Field Count"
FROM RDB$RELATION_FIELDS rf
WHERE rf,RDB$RELATION_NAME NOT STARTING WITH 'RDB$'
GROUP BY
rf.RDB$RELATION NAME;
Table Name |
ID |
Field Count |
COUNTRY |
128 |
2 |
CROSS_RATE |
139 |
4 |
CUSTOMER |
137 |
12 |
DEPARTMENT |
130 |
7 |
... и т.д.
Агрегаты во встроенных подзапросах
Выражение агрегатной функции- COUNT(), AVG() и т.д.- может принимать аргумент, который является выражением подзапроса, возвращающим скалярное значение. Например, далее результат запроса SELECT COUNT(*) передается на более высокий уровень в выражение SUMO, которое для каждой таблицы (RDB$RELATION_NAME) выводит произведение счетчика полей на количество индексов в таблице:
SELECT
r.RDB$RELATION_NAME,
SUM((SELECT COUNT(*) FROM RDB$RELATION_FIELDS rf
WHERE rf,RDB$RELATION_NAME = r.RDB$RELATION_NAME))
AS "Fields * Indexes"
FROM RDB$RELATIONS r
JOIN RDB$INDICES i
ON (i.RDB$RELATION_NAME = r.RDBSRELATION_NAME)
WHERE r.RDB$RELATION_NAME NOT STARTING WITH 'RDB$'
GROUP BY r.RDB$RELATION_NAME;
RDB$RELATION NAME Fields * Indexes
COUNTRY 2
CROSS_RATE 4
CUSTOMER 48
DEPARTMENT 35
... и т.д.
Агрегаты на смешанных уровнях группирования
Агрегатные функции для различных уровней группирования могут быть перемешаны в одном и том же группирующем запросе.
В следующем примере результат выражения, полученный из подзапроса, который выполняет COUNT() для столбца на самом низком уровне группы (RDB$INDICES), передается на уровень группирования. Предложение HAVING выполняет фильтрацию, определяемую двумя другими агрегатными функциями на нижнем уровне группы.
SELECT
r.RDB$RELATION_NAME,
MAX(i.RDB$STATISTICS) AS "Maxl",
/* одно агрегатное выражение, вложенное в другое */
(SELECT COUNT(*) || ' - ' || MAX(i.RDB$STATISTICS)
FROM RDB$RELATION_FIELDS rf
WHERE rf.RDB$RELATION_NAME = r.RDB$RELATION_NAME) AS "Max2"
FROM
RDB$RELAT IONS r
JOIN RDB$INDICES i
ON (i.RDB$RELATION NAME = r.RDB$RELATION_NAME)
WHERE r.RDB$RELATION_NAME NOT STARTING WITH 'RDB$'
GROOP BY
r.RDB$RELATION_NAME
HAVING
MIN(i.RDB$STATISTICS) MAX(i.RDB$STATISTICS);
RDB$RELATION NAME Maxl Max2
MTRANSACTION 000000000000001 18 - 1.000000000000000
MEMBER 0.0135135138407 12 - 0.01351351384073496
! ! !
ВНИМАНИЕ! Вы можете получить результат при выполнении этого запроса в Firebird 1.0.x, однако он будет некорректным.
. ! .
Вложенные агрегатные функции
Агрегатное выражение может быть вложено внутрь другого агрегатного выражения, если внутренняя агрегатная функция находится на более низком уровне (контексте), что иллюстрируется предыдущим запросом.
Пора дальше
В этой главе по языку манипулирования данными мы рассмотрели возможности SQL по трансформации абстрактных данных, хранимых в таблицах, в информацию, которую конечный пользователь читает в осмысленных контекстах. При некоторых условиях есть смысл сохранять постоянные определения полезных выходных наборов (виртуальных таблиц), чтобы не изобретать колесо каждый раз, когда требуется похожий набор. В следующей главе рассматриваются способы осуществления этого, в том числе и возможности просмотров.
- 11.2. Технология принятия решения в условиях чрезвычайной ситуации
- Условия CHECK
- 6. Улучшенные формы
- Условия копирования, распространения и модификации программных продуктов
- Предусловия и постусловия
- Условия поиска
- 1.3. Информационная безопасность в условиях функционирования в России глобальных сетей
- Постусловия
- Как применить эти условия договора к своим новым программам
- Использование идентификатора UID в качестве условия
- ОПЕРАЦИЯ УСЛОВИЯ: ?:
- Какие условия при продаже по телефону должны совпасть, чтобы покупка состоялась