Н. 3. Елманова. C++Builder 3.0, архитектура "клиент/сервер" и Internet
ных  выше  (касающиеся  всех  продавцов  и  всех категорий  продаваемых предметов), выглядит следующим образом:
	SALESMAN			Итого
ITEM	Ваня	Маня	Саня	
Стол	0	3500	1300	4800
Стул	600	500	500	1600
Шкаф	800	1200	2700	4700
Всего	1400	5200	4500	11100
Обратите внимание: все значения, содержащиеся в одном из столбцов исходной таблицы (в данном примере в столбце ITEM), образуют наименования столбцов кросс-таблиды, и все значения, содержащиеся в другом ?ТоЖце (в данном случае в столбце SALESMAN), образуют наименований строк кросс-таблицы. На пересечении строк и столбцов находятся суммы значений^ из еще одного столбца (в данном случае PAYMENT) для записей исходной таблицы, удовлетворяющих требованию равенства значения поля SALESMAN наименованию строки, а поля ITEM - наименованию столбца. Иными словами, в ячейках содержатся результаты запросов типа:
SELECT  SUM(PAYMENT)   FROM SALES WHERE   (SALESMAN='Ваня'   AND ~~1ТЕМ='стул' ).
Отметим, что на основании кросс-таблицы в общем случае невозможно ^восстановить исходную таблицу и при проектировании данных для информационной системы следует задуматься, а не является ли проектируемая таблица, по существу, кросс-таблицей, и не стоит ли заменить ее другой, 'а желаемую таблицу получать на основании процедуры кросс-табуляции? "Такие ошибки проектирования данных не так очевидны, как несоблюдение правил- нормализации, но последствия их иногда бывают весьма дорогостоящими. Одна из таких ошибок проектирования, встретившаяся одному из коллег автора в весьма дорогом и престижном западном коммерческом продукте, стоила пользователям этого продукта немалых средств, вложенных в генерацию отчетов, так как SQL-запросы к этой кросс-таблице, на основе которых создавались отчеты, иногда занимали несколько страниц.
Какие данные в общем случае можно поместить в кросс-таблицу? В приведенном выше примере была вычислена сумма продаж для каждого менеджера и каждого предмета. Можно задать другие вопросы: "Сколько столов продал Ваня?", или "Сколько стоил самый дорогой (или самый дешевый) стол, проданный Ваней?", или "Какова средняя стоимость столов, проданных Ваней?" Иными словами, помимо суммы можно вычислить
116
Новые компоненты для работы с базами данных
среднее, максимальное или минимальное значение поля PAYMENT для всех записей, удовлетворяющих условию равенства значения поля SALESMAN наименованию строки, а поля ITEM - наименованию столбца, а также число таких записей.
Если бы все ограничивалось только обычными двумерньщи кросс-таблицами, это было бы не так интересно - кросс-табуляцию можно выполнить с помощью практически любой электронной таблицы, например Microsoft Excel. Но в данном случае двумерная таблица представляет собой лишь простейший случай агрегатных данных.
В рассмотренном выше примере мы использовали поля ITEM и SALESMAN для образования дьух размерностей кросс-таблицы. Представим себе теперь, что нам нужны ответы на вопросы типа: "На какую сумму продал стулья Саня 3 апреля?" & этом случае условие, при котором значение поля PAYMENT добавляется к сумме, зависит уже от трех значений других полей - ITEM, SALESMAN и SALEDATE, и, если мы попытаемся построить аналог кросс-таблицы, получится обычный трехмерный куб с осями ITEM, SALESMAN и SALEDATE, сечения которого по любому Измерению представляют собой обычные двумерные кросс-таблицы:
Таблица 6.2. Сечения трехмерного куба с агрегатными данными
01.04.98		SALESMAN		Общий итог
ITEM	Ваня	Маня	Саня	
Стол	0	0	500	500
Стул	600	0	0	600
Шкаф	0	0	0	0
Общий итог	600	0	500	1100
02.04.98	SALESMAN			Общий итог
ITEM	Ваня	Маня	Саня	
Стол	0	0	0	0
Стул	0	О	0	0
Шкаф	800	0	0	800
Общий итог	800	0	0	800
117