<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="http://wiki2.linuxformat.ru/skins/common/feed.css?97"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://wiki2.linuxformat.ru/index.php?action=history&amp;feed=atom&amp;title=LXF134%3AOLAP</id>
		<title>LXF134:OLAP - История изменений</title>
		<link rel="self" type="application/atom+xml" href="http://wiki2.linuxformat.ru/index.php?action=history&amp;feed=atom&amp;title=LXF134%3AOLAP"/>
		<link rel="alternate" type="text/html" href="http://wiki2.linuxformat.ru/index.php?title=LXF134:OLAP&amp;action=history"/>
		<updated>2026-05-14T04:16:13Z</updated>
		<subtitle>История изменений этой страницы в вики</subtitle>
		<generator>MediaWiki 1.11.1</generator>

	<entry>
		<id>http://wiki2.linuxformat.ru/index.php?title=LXF134:OLAP&amp;diff=12538&amp;oldid=prev</id>
		<title>Crazy Rebel: /* Ба­за дан­ных */</title>
		<link rel="alternate" type="text/html" href="http://wiki2.linuxformat.ru/index.php?title=LXF134:OLAP&amp;diff=12538&amp;oldid=prev"/>
				<updated>2011-09-02T09:21:37Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;Ба­за дан­ных&lt;/span&gt;&lt;/p&gt;

			&lt;table style=&quot;background-color: white; color:black;&quot;&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;tr&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;← Предыдущая&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Версия 09:21, 2 сентября 2011&lt;/td&gt;
			&lt;/tr&gt;
		&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 125:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 125:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;/source&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;/source&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;{{Врезка|Содержание=[[Изображение:LXF134_66_1.jpg|300px|Рис. 2.]] Рис. 2. Фраг­мент ги­пер­ку­ба с дан­ны­ми о про­да­жах в руб­лях, со­дер­жа­ще­го во­семь осей&lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;.&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;{{Врезка|Содержание=[[Изображение:LXF134_66_1.jpg|300px|Рис. 2.]] Рис. 2. Фраг­мент ги­пер­ку­ба с дан­ны­ми о про­да­жах в руб­лях, со­дер­жа­ще­го во­семь осей.|Ширина=300px}}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;[[Изображение:LXF134_66_2.jpg|300px|Рис. 3.]] Рис 3. Вы­бор осей ги­пер­ку­ба для фор­ми­ро­ва­ния про­ек­ции&lt;/del&gt;.|Ширина=300px}}&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Ося­ми ги­пер­ку­ба в дан­ном слу­чае яв­ля­ют­ся: 0 – ка­те­го­рия, 1 – то­вар, 2 – про­да­вец, 3 – груп­па, 4 – по­ку­па­тель, 5 – год, 6 – ме­сяц, 7 – день. Фраг­мент ги­пер­ку­ба или таб­ли­цы, по­лу­чен­ной в ре­зуль­та­те вы­полнения дан­но­го за­про­са, мож­но ви­деть на рис. 2.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Ося­ми ги­пер­ку­ба в дан­ном слу­чае яв­ля­ют­ся: 0 – ка­те­го­рия, 1 – то­вар, 2 – про­да­вец, 3 – груп­па, 4 – по­ку­па­тель, 5 – год, 6 – ме­сяц, 7 – день. Фраг­мент ги­пер­ку­ба или таб­ли­цы, по­лу­чен­ной в ре­зуль­та­те вы­полнения дан­но­го за­про­са, мож­но ви­деть на рис. 2.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;{{Врезка|Содержание=[[Изображение:LXF134_66_2.jpg|200px|Рис. 3.]] Рис 3. Вы­бор осей ги­пер­ку­ба для фор­ми­ро­ва­ния про­ек­ции.|Ширина=200px}}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;===Фор­мат пред­став­ления===&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;===Фор­мат пред­став­ления===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Crazy Rebel</name></author>	</entry>

	<entry>
		<id>http://wiki2.linuxformat.ru/index.php?title=LXF134:OLAP&amp;diff=12533&amp;oldid=prev</id>
		<title>Crazy Rebel: викификация, оформление, иллюстрация</title>
		<link rel="alternate" type="text/html" href="http://wiki2.linuxformat.ru/index.php?title=LXF134:OLAP&amp;diff=12533&amp;oldid=prev"/>
				<updated>2011-09-02T09:15:17Z</updated>
		
		<summary type="html">&lt;p&gt;викификация, оформление, иллюстрация&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая статья&lt;/b&gt;&lt;/p&gt;&lt;div&gt;: '''Мно­го­мер­ный ана­лиз''' Раз­бо­р ре­аль­ной про­грам­мы, вы­являю­щей за­ко­но­мер­но­сти&lt;br /&gt;
&lt;br /&gt;
==OLAP: Ана­лиз данных и СПО==&lt;br /&gt;
&lt;br /&gt;
: Вы­ло­жить бе­лый хлеб по со­сед­ст­ву с мо­ло­ком или кол­ба­сой? От­вет на этот во­прос по­мо­жет най­ти мно­го­мер­ный ана­лиз дан­ных, а '''Вя­че­слав Оло­ни­чев''' и '''Ан­д­рей Се­нов''' реа­ли­зу­ют его на ''Qt'' и ''C++''.&lt;br /&gt;
&lt;br /&gt;
Мно­го­мер­ный ана­лиз дан­ных или OLAP – это тех­но­ло­гия, ин­туи­тив­но по­нят­ная лю­бо­му, кто когда-ли­бо занимал­ся обоб­щением дан­ных по про­да­жам, вы­пуску про­дук­ции и то­му по­доб­ным. Эта тех­но­ло­гия востре­бо­ва­на прак­ти­че­ски по­все­ме­ст­но, на­чи­ная от ма­лень­кой мастер­ской или фер­мер­ско­го хо­зяй­ства и за­кан­чи­вая министер­ством или цен­траль­ным офи­сом транс­на­цио­наль­ной кор­по­ра­ции. Со­от­вет­ствен­но, и ре­шений для нее су­ще­ству­ет доста­точ­но мно­го. Здесь мож­но най­ти и нестан­дарт­ные рас­ши­рения SQL ти­па ''pivot'' в ''Access'', под­клю­чае­мые мо­ду­ли для элек­трон­ных таб­лиц или той же «''1С''», пре­ве­ли­кое мно­же­ство про­грамм на ''Delphi'' с его ''Decision Cube'' или ''VBA'', и, на­конец, ин­ст­ру­мен­та­рий для мно­го­мер­но­го ана­ли­за на сто­роне сер­ве­ра от Microsoft или Oracle. Наи­бо­лее удоб­ные и про­дви­ну­тые ре­шения в дан­ной об­ласти пред­на­зна­че­ны в пер­вую оче­редь для боль­ших кор­по­ра­ций и име­ют со­от­вет­ствую­щую стои­мость. Ис­поль­зо­вание же элек­трон­ных таб­лиц крайне тру­до­ем­ко и неэф­фек­тив­но. И кро­ме то­го, все ука­зан­ные ре­шения яв­ля­ют­ся про­прие­тар­ны­ми.&lt;br /&gt;
&lt;br /&gt;
Опи­сы­вае­мая здесь про­грам­ма (вы най­де­те ее пол­ные ис­ход­ные тек­сты на '''LXFDVD''') от­ли­ча­ет­ся от имею­щих­ся в пер­вую оче­редь тем, что ис­поль­зу­ет толь­ко сво­бод­ный код и са­ма яв­ля­ет­ся от­кры­той. Пред­на­зна­че­на она для мно­го­мер­но­го ана­ли­за дан­ных на сто­роне кли­ен­та, что и оп­ре­де­ля­ет об­ласть ее по­тен­ци­аль­но­го при­менения: неболь­шие и средние пред­при­ятия, для ко­то­рых SQL-за­прос, от­би­раю­щий дан­ные за пять-шесть лет, бу­дет вы­полнен на сер­ве­ре и пе­ре­дан по локаль­ной се­ти кли­ен­ту за при­ем­ле­мое вре­мя.&lt;br /&gt;
&lt;br /&gt;
Про­грам­ма осно­ва­на на вы­полнении всех опе­ра­ций по мно­го­мер­но­му ана­ли­зу с ис­поль­зо­ванием ти­по­вых струк­тур дан­ных в ОЗУ, что долж­но обес­пе­чить доста­точ­но вы­со­кую эф­фек­тив­ность при уме­рен­ных за­тра­тах па­мя­ти. Наи­бо­лее пол­ная, удоб­ная и эф­фек­тив­ная реа­ли­за­ция ти­по­вых струк­тур дан­ных – это па­ра­мет­ри­зо­ван­ные кон­тейнеры на язы­ке ''С++'', та­кие как стан­дарт­ная биб­лио­те­ка шаб­ло­нов ''STL'' и биб­лио­те­ка шаб­ло­нов ''Qt''.&lt;br /&gt;
&lt;br /&gt;
Как кон­тейнеры ''STL'', так и кон­тейнеры ''Qt'' – это сво­бод­ное ПО. Разница ме­ж­ду ними на­столь­ко ма­ла, что фраг­мен­ты ис­ход­но­го ко­да, со­дер­жа­щие об­ра­щение к ''STL'', мож­но пе­ре­де­лать в код, ра­бо­таю­щий с шаб­ло­на­ми ''Qt'' (и на­обо­рот), бу­к­валь­но за па­ру ми­нут.&lt;br /&gt;
&lt;br /&gt;
В на­шем слу­чае ис­поль­зу­ют­ся шаб­ло­ны ''Qt'', по сле­дую­щей при­чине: по­сколь­ку гра­фи­че­ский ин­тер­фейс про­грам­мы вы­полнен с ис­поль­зо­ванием биб­лио­те­ки ''Qt'' и доступ к ба­зе дан­ных про­из­во­дит­ся так­же сред­ства­ми ''Qt'', то шаб­ло­ны ''Qt'' сле­ду­ет при­ме­нять не толь­ко из прин­ци­па еди­но­об­ра­зия, но и ради эф­фек­тив­но­сти, так как они тес­но взаи­мо­дей­ству­ют с основ­ной биб­лио­те­кой. Мо­дуль мно­го­мер­но­го ана­ли­за в про­грам­ме вы­де­лен в от­дель­ный класс, по­это­му его лег­ко адап­ти­ро­вать к дру­гой плат­фор­ме или биб­лио­те­ке. Кста­ти го­во­ря, пер­вая вер­сия про­грам­мы бы­ла вы­полнена на ''C++ Builder'' с ис­поль­зо­ванием ''STL'', по­том ин­тер­фейс был пе­репи­сан на ''Qt3'' в ''KDevelop'', но ''STL'' со­хранена. А те­ку­щая реа­ли­за­ция вы­полнена на ''Qt4'' в сре­де ''Qt Creator''.&lt;br /&gt;
&lt;br /&gt;
Для мно­го­мер­но­го ана­ли­за дан­ных на сто­роне кли­ен­та тре­бу­ет­ся ре­шить сле­дую­щие за­да­чи:&lt;br /&gt;
# Вы­бор струк­ту­ры дан­ных для со­хранения в ОЗУ ре­зуль­та­тов SQL-за­про­са и тре­бо­вания к тек­сту SQL-за­про­са.&lt;br /&gt;
# Фор­мат пред­став­ления вы­бран­ных осей ги­пер­ку­ба для фор­ми­ро­вания его про­ек­ции на плоскость.&lt;br /&gt;
# Фор­ми­ро­вание са­мой про­ек­ции.&lt;br /&gt;
# Фор­ми­ро­вание ито­гов.&lt;br /&gt;
&lt;br /&gt;
При ре­шении дан­ных за­дач бу­дем по­сле­до­ва­тель­но при­дер­жи­вать­ся прин­ци­па по­все­ме­ст­но ис­поль­зо­вать па­ра­мет­ри­зо­ван­ные кон­тейнеры. Это стрем­ление не столь­ко к со­блю­дению еди­но­го сти­ля, сколь­ко к эф­фек­тив­но­сти, так как по­зво­ля­ет све­сти к миниму­му все '''if-else'''’ы и '''switch-case'''’ы и мак­си­маль­но ис­поль­зо­вать оп­ти­ми­зи­ро­ван­ный код па­ра­мет­ри­зо­ван­ных кон­тейнеров.&lt;br /&gt;
&lt;br /&gt;
===''STL'' и OLAP===&lt;br /&gt;
&lt;br /&gt;
Пре­ж­де чем уг­луб­лять­ся в де­та­ли, разъ­яс­ним не­сколь­ко тер­ми­нов. Стан­дарт­ная биб­лио­те­ка шаб­ло­нов (Standard Template Library, ''STL'') – на­бор со­гла­со­ван­ных обоб­щен­ных ал­го­рит­мов, кон­тей­не­ров, средств дос­ту­па к их со­дер­жи­мо­му и раз­лич­ных вспо­мо­га­тель­ных функ­ций (http://ru.wikipedia.org/wiki/Стан­дарт­ная_би­би­ло­те­ка_шаб­ло­нов).&lt;br /&gt;
&lt;br /&gt;
OLAP (On Line Analytical Processing – ин­те­рак­тив­ная ана­ли­ти­че­ская об­ра­бот­ка дан­ных) – один из спо­со­бов пред­став­ле­ния и ана­ли­за дан­ных. При этом ин­фор­ма­ция пред­став­ля­ет­ся в ви­де мно­го­мер­но­го ку­ба с воз­мож­но­стью про­из­воль­но­го ма­ни­пу­ли­ро­ва­ния ею. Мно­го­мер­ные мо­де­ли рас­смат­ри­ва­ют дан­ные ли­бо как фак­ты с со­от­вет­ст­вую­щи­ми чис­лен­ны­ми па­ра­мет­ра­ми, ли­бо как тек­сто­вые из­ме­ре­ния, ко­то­рые ха­рак­те­ри­зу­ют эти фак­ты. (Ка­ши­рин И.Ю., Сем­чен­ков С.Ю. Ин­те­рак­тив­ная ана­ли­ти­че­ская об­ра­бот­ка дан­ных в со­вре­мен­ных OLAP сис­те­мах // Биз­нес-ин­фор­ма­ти­ка – 2009. – № 2. С.12–19. См. так­же http://ru.wikipedia.org/wiki/OLAP).&lt;br /&gt;
&lt;br /&gt;
===Вы­бор струк­ту­ры дан­ных===&lt;br /&gt;
&lt;br /&gt;
SQL-за­прос, по­став­ляю­щий дан­ные для мно­го­мер­но­го ана­ли­за, дол­жен иметь вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=sql&amp;gt;&lt;br /&gt;
 select ось0, ось1, ... осьN, val&lt;br /&gt;
 from ... Inner join ... on ...&lt;br /&gt;
 ...&lt;br /&gt;
 where some_date between :d1 and :d2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где '''ось0, ось1, …, осьN''' – ре­зуль­та­ты из­ме­рений на осях ги­пер­ку­ба; '''val''' – ана­ли­зи­руе­мое зна­чение, со­дер­жа­щее­ся в ячей­ке ги­пер­ку­ба; ''':d1,:d2''' – па­ра­мет­ры, за­даю­щие ин­тер­вал вре­мени, за ко­то­рый про­из­во­дит­ся ана­лиз.&lt;br /&gt;
&lt;br /&gt;
За­прос воз­вра­ща­ет ре­ля­ци­он­ную таб­ли­цу, в ко­то­рой ат­ри­бу­ты, со­от­вет­ствую­щие ре­зуль­та­там из­ме­рений, мо­гут иметь са­мые раз­но­об­раз­ные ти­пы, а по­следний ат­ри­бут – '''val''' – прак­ти­че­ски все­гда яв­ля­ет­ся чис­лом с пла­ваю­щей точ­кой.&lt;br /&gt;
&lt;br /&gt;
На­ша за­да­ча – реа­ли­зо­вать не толь­ко универ­саль­ный спо­соб со­хранения ре­зуль­та­тов в ОЗУ, но и обес­пе­чить воз­мож­ность по­строения как про­стых, так и со­став­ных клю­чей по ре­зуль­та­там из­ме­рений на осях ги­пер­ку­ба, ко­то­рые бу­дут необ­хо­ди­мы как для упо­ря­до­чи­вания, так и для по­иска ин­фор­ма­ции. По­это­му все ре­зуль­та­ты из­ме­рений сле­ду­ет при­вести к од­но­му ти­пу в са­мом на­ча­ле, еще до раз­ме­щения в ОЗУ. В ка­че­стве та­ко­го ти­па был вы­бран стро­ко­вый. Это объ­яс­ня­ет­ся тем, что боль­шин­ство ат­ри­бу­тов, со­от­вет­ствую­щих ре­зуль­та­там из­ме­рений на осях ги­пер­ку­ба, из­на­чаль­но име­ют стро­ко­вый тип – это на­име­но­вания то­ва­ров, пред­при­ятий, фа­ми­лии ра­ботников и то­му по­доб­ное. Все дру­гие ти­пы все­гда мож­но пре­об­ра­зо­вать к стро­ко­во­му. Что ка­са­ет­ся дат, то ес­ли их пре­об­ра­зо­вать в стро­ко­вый вид при по­мо­щи SQL-функ­ции '''cast''' в так на­зы­вае­мом ар­мей­ском фор­ма­те – «гггг.мм.дд» – то упо­ря­до­чи­вание строк в ал­фа­вит­ном по­ряд­ке бу­дет со­от­вет­ство­вать упо­ря­до­чи­ванию дат в по­ряд­ке воз­растания.&lt;br /&gt;
&lt;br /&gt;
Та­ким об­ра­зом по­лу­ча­ем:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
 typedef QVector&amp;lt;QString&amp;gt; s_keys;&lt;br /&gt;
 struct l_cube{&lt;br /&gt;
  s_keys dims;&lt;br /&gt;
 double r;&lt;br /&gt;
 };&lt;br /&gt;
 typedef QVector&amp;lt;l_cube&amp;gt; data_cube;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где '''s_keys''' – век­тор, в ко­то­рый по­ме­ща­ют­ся ре­зуль­та­ты из­ме­ре­ний; '''l_cube''' – струк­ту­ра для со­хра­не­ния од­ной стро­ки, воз­вра­щае­мой за­про­сом; '''data_cube''' – век­тор, для со­хра­не­ния в ОЗУ таб­ли­цы, воз­вра­щае­мой за­про­сом.&lt;br /&gt;
&lt;br /&gt;
За­кач­ка ин­фор­ма­ции в па­мять, ес­ли смот­реть из­нут­ри, осу­ще­ст­в­ля­ет­ся сле­дую­щим об­ра­зом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
 class hyper_cube{&lt;br /&gt;
 protected:&lt;br /&gt;
     data_cube dc;&lt;br /&gt;
     l_cube line;&lt;br /&gt;
 ...&lt;br /&gt;
 public:&lt;br /&gt;
     void add(s_keys sk, double res){&lt;br /&gt;
       line.r = res;&lt;br /&gt;
       for(int i=0; i&amp;lt;N; i++) line.dims[i]=sk[i];&lt;br /&gt;
       dc.push_back(line);&lt;br /&gt;
     }&lt;br /&gt;
 ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А снару жи это выглядит так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
 hyper_cube HC;&lt;br /&gt;
 s_keys VK;&lt;br /&gt;
 QSqlQuery* psql;&lt;br /&gt;
 QDate d1,d2;&lt;br /&gt;
 psql­&amp;gt;bindValue(“:d1”,QVariant(d1));&lt;br /&gt;
 psql­&amp;gt;bindValue(“:d2”,QVariant(d2));&lt;br /&gt;
 if(psql­&amp;gt;exec()){&lt;br /&gt;
     while ( psql­&amp;gt;next() ) {&lt;br /&gt;
       for(int i=0; i&amp;lt;Nax; i++){&lt;br /&gt;
          VK[i] = psql­&amp;gt;value(i).toString() + '\n';&lt;br /&gt;
       }&lt;br /&gt;
       HC.add(VK, psql­&amp;gt;value(Nax).toDouble());&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь '''Nax''' – ко­ли­че­ство осей ги­пер­ку­ба. Ес­ли ис­поль­зо­вать од­но­на­прав­лен­ный за­прос, то при­ве­ден­ный код бу­дет доста­точ­но эф­фек­тив­ным.&lt;br /&gt;
&lt;br /&gt;
===Ба­за дан­ных===&lt;br /&gt;
&lt;br /&gt;
{{Врезка|Содержание=[[Изображение:LXF134_65_1.jpg|300px|Рис. 1.]] Рис. 1. ER-диа­грам­ма ба­зы дан­ных «Оп­то­вая тор­гов­ля сто­ло­вой по­су­дой».|Ширина=300px}}&lt;br /&gt;
&lt;br /&gt;
В ка­че­стве при­ме­ра ис­поль­зу­ем фраг­мент ба­зы дан­ных пред­приятия, занимаю­ще­го­ся мел­ко­оп­то­вой про­да­жей сто­ло­вой по­су­ды. Ба­за дан­ных реа­ли­зо­ва­на на ''SQLite'' (ка­та­лог '''primer''' в ис­ход­ных тек­стах про­грам­мы), а ее ER-диа­грам­ма пред­став­ле­на на рис. 1.&lt;br /&gt;
&lt;br /&gt;
В ука­зан­ной ба­зе дан­ных име­ют­ся сле­дую­щие таб­ли­цы: '''kat''' – ка­те­го­рии то­ва­ра, '''tov''' – то­ва­ры, '''prod''' – про­дав­цы, '''grup''' – груп­пы по­ку­па­те­лей, '''pok''' – по­ку­па­те­ли; '''cen''' – це­ны на то­ва­ры, '''sales''' – про­да­жи.&lt;br /&gt;
&lt;br /&gt;
Сле­дую­щий за­прос воз­вра­тит ги­пер­куб с дан­ны­ми о про­да­жах в руб­лях, со­дер­жа­щий 8 осей:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=sql&amp;gt;&lt;br /&gt;
 select k.nam, t.nam, pr.nam, g.nam, pk.nam,&lt;br /&gt;
 substr(cast(s.dat as char(32)),1,4) as ye,&lt;br /&gt;
 substr(cast(s.dat as char(32)),1,7) as mo,&lt;br /&gt;
 substr(cast(s.dat as char(32)),1,10) as da,&lt;br /&gt;
 s.kvo*c.cena as sum&lt;br /&gt;
 from sales s inner join cen c on c.id_tov=s.id_tov&lt;br /&gt;
 inner join tov t on t.id=s.id_tov&lt;br /&gt;
 inner join prod pr on pr.id=s.id_prod&lt;br /&gt;
 inner join pok pk on pk.id=s.id_pok&lt;br /&gt;
 inner join grup g on g.id=pk.id_gr&lt;br /&gt;
 inner join kat k on k.id=t.id_kat&lt;br /&gt;
 where c.dat=(select max(dat) from cen where&lt;br /&gt;
 cen.id_tov=s.id_tov and dat&amp;lt;=s.dat)&lt;br /&gt;
 and s.dat between :d1 and :d2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Врезка|Содержание=[[Изображение:LXF134_66_1.jpg|300px|Рис. 2.]] Рис. 2. Фраг­мент ги­пер­ку­ба с дан­ны­ми о про­да­жах в руб­лях, со­дер­жа­ще­го во­семь осей.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:LXF134_66_2.jpg|300px|Рис. 3.]] Рис 3. Вы­бор осей ги­пер­ку­ба для фор­ми­ро­ва­ния про­ек­ции.|Ширина=300px}}&lt;br /&gt;
&lt;br /&gt;
Ося­ми ги­пер­ку­ба в дан­ном слу­чае яв­ля­ют­ся: 0 – ка­те­го­рия, 1 – то­вар, 2 – про­да­вец, 3 – груп­па, 4 – по­ку­па­тель, 5 – год, 6 – ме­сяц, 7 – день. Фраг­мент ги­пер­ку­ба или таб­ли­цы, по­лу­чен­ной в ре­зуль­та­те вы­полнения дан­но­го за­про­са, мож­но ви­деть на рис. 2.&lt;br /&gt;
&lt;br /&gt;
===Фор­мат пред­став­ления===&lt;br /&gt;
&lt;br /&gt;
Сле­дую­щая про­бле­ма – вы­бор поль­зо­ва­те­лем осей ги­пер­ку­ба для фор­ми­ро­вания про­ек­ции и пе­ре­да­ча этой ин­фор­ма­ции ко­ду, ко­то­рый и бу­дет ее фор­ми­ро­вать. Для поль­зо­ва­те­ля есте­ствен­ным пред­став­лением осей ги­пер­ку­ба яв­ля­ют­ся два спи­ска, один для оси '''X '''про­ек­ции и вто­рой – для оси '''Y''', до­пускаю­щих мно­же­ствен­ный вы­бор и пе­ре­ме­щение эле­мен­тов спи­ска от­но­си­тель­но друг дру­га. Эти два тре­бо­вания яв­ля­ют­ся обя­за­тель­ны­ми; про­грам­ма, не от­ве­чаю­щая им, не пред­став­ля­ет боль­шо­го ин­те­ре­са для прак­ти­ки.&lt;br /&gt;
&lt;br /&gt;
Для при­ло­жения ис­поль­зо­вание на­име­но­ваний осей не со­всем удоб­но – пред­поч­ти­тельней ис­поль­зо­вать но­ме­ра: ведь дан­ные из­ме­рений хра­нят­ся в век­то­рах, и ин­декс в век­то­ре од­но­знач­но со­от­вет­ству­ет но­ме­ру оси. По­сколь­ку эле­мен­ты спи­ска мо­гут из­ме­нять вза­им­ное рас­по­ло­жение, то их те­ку­щие но­ме­ра уже не бу­дут со­от­вет­ство­вать но­ме­рам осей ги­пер­ку­ба. Для ре­шения дан­ной за­да­чи восполь­зу­ем­ся сло­ва­рем '''QMap&amp;lt;QString, int&amp;gt;''', ко­то­рый по­зво­лит по вы­бран­ной поль­зо­ва­те­лем стро­ке с на­званием оси оп­ре­де­лить ее но­мер. До­пустим, что, как пред­став­ле­но на рис. 3, поль­зо­ва­тель ре­шил проана­ли­зи­ро­вать, как рас­пре­де­ля­ют­ся про­да­жи по го­дам и груп­пам по­ку­па­те­лей, с од­ной сто­ро­ны, и по ка­те­го­ри­ям то­ва­ров и про­дав­цам, с дру­гой. Для это­го ему при­шлось пе­ре­местить ось ги­пер­ку­ба «Год» вверх по спи­ску для про­ек­ции на ось '''X''' – ведь его ин­те­ре­су­ет рас­пре­де­ление про­даж по груп­пам по­ку­па­те­лей в пре­де­лах ка­ж­до­го го­да; ина­че у него по­лу­чи­лось бы рас­пре­де­ление про­даж по го­дам в пре­де­лах ка­ж­дой груп­пы.&lt;br /&gt;
Оп­ре­де­лим сле­дую­щие пе­ре­мен­ные: '''myAxes''' – мас­сив '''QVector&amp;lt;QString&amp;gt;''', со­дер­жа­щий на­име­но­вания осей ги­пер­ку­ба; '''lstX''' и '''lstY''' – спи­ски '''QListWidget''', пред-на­зна­чен­ные для ото­бра­жения и вы­бо­ра осей ги­пер­ку­ба для осей '''X''' и '''Y''' про­ек­ции; '''m_axe''' – сло­варь '''QMap&amp;lt;QString,int&amp;gt;''', по­зво­ляю­щий по­лу­чить по­ряд­ко­вые но­ме­ра по на­име­но­ваниям осей ги­пер­ку­ба; '''xJ, yI''' – мас­си­вы '''QVector&amp;lt;int&amp;gt;''', со­дер­жа­щие но­ме­ра осей ги­пер­ку­ба, ото­бран­ные для ото­бра­жения на оси '''X''' и '''Y''' про­екции. В ре­зуль­та­те, в при­ме­ре на рис. 3, мас­сив '''xJ''' бу­дет со­дер­жать чис­ла 5 и 3, а мас­сив '''yI''' – чис­ла 0 и 2.&lt;br /&gt;
&lt;br /&gt;
===Фор­ми­ро­вание про­ек­ции===&lt;br /&gt;
&lt;br /&gt;
При фор­ми­ро­вании от­че­та бу­дем ис­поль­зо­вать сле­дую­щие пра­ви­ла: в ячей­ки про­ек­ции по­ме­ща­ют­ся толь­ко сум­мы, а ито­ги мо­гут со­дер­жать или сум­мы, или средние, или миниму­мы/мак­си­му­мы зна­чений, со­дер­жа­щих­ся в клет­ках про­ек­ции, в за­ви­си­мо­сти от вы­бо­ра поль­зо­ва­те­ля. Та­ким об­ра­зом, при вы­бо­ре мак­си­му­ма мы бу­дем по­лу­чать мак­си­маль­ную сум­му про­даж ка­те­го­рии то­ва­ров про­дав­цом ка­ж­дой груп­пе по­тре­би­те­лей за год, а не мак­си­маль­ную единич­ную про­да­жу.&lt;br /&gt;
&lt;br /&gt;
Как про­ек­цию, так и ито­ги бу­дем по­ме­щать в дву­мер­ный мас­сив чи­сел с пла­ваю­щей точ­кой. Зна­чения из­ме­рения по осям «при­ри­со­вы­ва­ют­ся» к от­че­ту на по­следнем эта­пе, когда он ото­бра­жа­ет­ся в '''QTableWidget''' в окне диа­ло­га. Раз­мер дан­но­го дву­мер­но­го мас­си­ва из­вестен на мо­мент фор­ми­ро­вания, и по­это­му мож­но ис­поль­зо­вать обыч­ный ди­на­ми­че­ский мас­сив. Од­на­ко, про­сто из прин­ци­па еди­но­об­ра­зия, бу­дем ис­поль­зо­вать тип дан­ных '''Qvector&amp;lt;QVector&amp;lt;double&amp;gt;&amp;gt;'''.&lt;br /&gt;
&lt;br /&gt;
На рис. 4 пред­став­лен фраг­мент про­ек­ции и ито­гов; за­го­лов­ки ко­ло­нок таб­ли­цы со­дер­жат ре­зуль­та­ты из­ме­рений по осям ги­пер­ку­ба – «Год» и «Груп­па пред­при­ятий», ко­то­рые от­ра­же­ны на ось '''X''' про­ек­ции. В клет­ках про­ек­ции пред­став­ле­ны сум­мы про­даж, рас­пре­де­лен­ные по го­дам и груп­пам пред­при­ятий, с од­ной сто­ро­ны, и ка­те­го­ри­ям то­ва­ров и про­дав­цам, с дру­гой сто­ро­ны. Ито­ги вни­зу пред­став­ля­ют сум­мы по го­дам и груп­пам пред­при­ятий. Строч­ка ниже со­дер­жит сум­мы про­даж по го­дам, а са­мая пра­вая ко­лон­ка – сум­мы про­даж по ка­те­го­ри­ям то­ва­ров.&lt;br /&gt;
&lt;br /&gt;
{{Врезка|Содержание=[[Изображение:LXF134_67_1.jpg|400px|Рис. 4.]] Рис. 4. Фраг­мент от­че­та, ге­не­ри­руемо­го про­грам­мой.|Ширина=400px}}&lt;br /&gt;
&lt;br /&gt;
За­да­ча за­клю­ча­ет­ся в том, что­бы вы­брать из таб­ли­цы с резуль­та­та­ми за­про­са уникаль­ные со­че­тания из­ме­рен­ных зна­чений на вы­бран­ных осях ги­пер­ку­ба и упо­ря­до­чить их в ал­фа­вит­ном по­ряд­ке. А за­тем сле­ду­ет ото­брать зна­чения ана­ли­зи­руе­мой ве­ли­чи­ны, в дан­ном слу­чае – сум­мы про­даж, из со­от­вет­ствую­щих стро­чек таб­ли­цы и про­сум­ми­ро­вать их в нуж­ных клет­ках про­ек­ции. Для ре­шения за­да­чи бу­дем ис­поль­зо­вать сло­варь '''QMap&amp;lt;QString, int&amp;gt;'''.&lt;br /&gt;
&lt;br /&gt;
В дан­ном фраг­мен­те ко­да сканиру­ет­ся таб­ли­ца '''dc''', со­дер­жа­щая ре­зуль­та­ты за­про­са к ба­зе дан­ных, как по­ка­за­но на рис. 2. Век­то­ры '''xJ''' и '''yI''', как уже бы­ло ска­за­но, со­дер­жат но­ме­ра вы­бран­ных осей, {5, 3} и {0, 2} со­от­вет­ствен­но. В хо­де вы­полнения цик­ла стро­ка '''xs''' бу­дет по­сле­до­ва­тель­но принимать зна­чения «2007\nВосток\n», «2007\nЮг\n», «2007\nЗапад\n», «2007\nСеверг\n» и т. д., а стро­ка '''ys''' – «се­реб­ро\nКсюша\n», «се­реб­ро\nМаша\n», «се­реб­ро\nДаша\n», «се­реб­ро\nМаша\n» и т. д. И все эти стро­ки, яв­ляю­щие­ся пол­ны­ми со­став­ны­ми клю­ча­ми для осей''' X''' и '''Y''' про­ек­ции ги­пер­ку­ба, бу­дут по­ме­щать­ся как клю­чи в сло­ва­ри '''pX''' и '''pY'''. Зна­чения, по­ме­щае­мые в сло­ва­ри, на дан­ном эта­пе не важ­ны, и по­это­му для них ис­поль­зу­ет­ся '''-1'''. Сло­варь мо­жет со­дер­жать толь­ко непо­вто­ряю­щие­ся клю­чи, по­это­му по за­вер­шении цик­ла сло­ва­ри '''pX''' и '''pY''' бу­дут со­дер­жать все уникаль­ные зна­чения пол­ных со­став­ных клю­чей, со­дер­жа­щих­ся в таб­ли­це с дан­ны­ми.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
 QString xs, ys;&lt;br /&gt;
 Qmap&amp;lt;QString,int&amp;gt; pX,pY;&lt;br /&gt;
 int Hx=xJ.size();&lt;br /&gt;
 int Hy=yI.size();&lt;br /&gt;
 for(int i=0; i&amp;lt;dc.size(); i++){&lt;br /&gt;
   xs=””; ys=””;&lt;br /&gt;
   for(int x=0; x&amp;lt;Hx; x++) xs=xs+dc[i].dims[xJ[x]];&lt;br /&gt;
   for(int y=0; y&amp;lt;Hy; y++) ys=ys+dc[i].dims[yI[y]];&lt;br /&gt;
   (*pY)[ys]=­1; (*pX)[xs]=­1;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сле­дую­щий фраг­мент ко­да пе­ре­би­ра­ет все клю­чи, со­дер­жа­щие­ся в сло­ва­рях '''pX''' и '''pY''', при по­мо­щи ите­ра­то­ра, и при­сваи­ва­ет им мо­но­тон­но воз­растаю­щие це­ло­чис­лен­ные зна­чения. В ре­зуль­та­те на­ши сло­ва­ри со­дер­жат в ка­че­стве клю­чей на­име­но­вания строк и ко­ло­нок про­ек­ции, а в ка­че­стве зна­чений – но­ме­ра со­от­вет­ствую­щих строк и ко­ло­нок. Это как раз то, что и тре­бу­ет­ся для за­полнения яче­ек про­ек­ции.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
 Qmap&amp;lt;QString,int&amp;gt;::iterator it;&lt;br /&gt;
 int m,n;&lt;br /&gt;
 m=0;&lt;br /&gt;
 for(it=(*pY).begin(); it!=(*pY).end(); it++)&lt;br /&gt;
  {it.value()=m++;}&lt;br /&gt;
 n=0;&lt;br /&gt;
 for(it=(*pX).begin(); it!=(*pX).end(); it++)&lt;br /&gt;
  {it.value()=n++;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В ниже­сле­дую­щем цик­ле зна­чения пол­ных со­став­ных клю­чей опять восста­нав­ли­ва­ют­ся из зна­чений из­ме­рений, а по ним оп­ре­де­ля­ют­ся ко­ор­ди­на­ты ячей­ки про­ек­ции, к со­дер­жи­мо­му ко­то­рой до­бав­ля­ет­ся зна­чение ана­ли­зи­руе­мой ве­ли­чи­ны из оче­ред­ной строч­ки сканируе­мой таб­ли­цы с ре­зуль­та­та­ми за­про­са.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
 int I,J;&lt;br /&gt;
 for(int i=0; i&amp;lt;dc.size(); i++){&lt;br /&gt;
  xs=””; ys=””;&lt;br /&gt;
  for(int x=0; x&amp;lt;Hx; x++) xs=xs+dc[i].dims[xJ[x]];&lt;br /&gt;
  for(int y=0; y&amp;lt;Hy; y++) ys=ys+dc[i].dims[yI[y]];&lt;br /&gt;
  I = (*pY)[ys];&lt;br /&gt;
  J = (*pX)[xs];&lt;br /&gt;
  dp[I][J]+=dc[i].r;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Фор­ми­ро­ва­ние ито­гов===&lt;br /&gt;
&lt;br /&gt;
Оста­лась по­след­няя про­бле­ма – фор­ми­ро­вание ито­гов по пол­ным и частич­ным клю­чам. Как уже бы­ло ска­за­но вы­ше, на­до по­лу­чить сум­мы про­даж, рас­пре­де­лен­ные по груп­пам по­тре­би­те­лей в пре­де­лах го­да, а так­же сум­мы про­даж по го­дам. Так вот, «Год\nГруп­па_ком­паний\n» – это пол­ный ключ, имею­щий уникаль­ное зна­чение для ка­ж­дой ко­лон­ки про­ек­ции, а «Год\n» – это частич­ный ключ. Ес­ли по­стро­ить сло­ва­ри с частич­ны­ми клю­ча­ми, то мож­но оп­ре­де­лить как ко­ор­ди­на­ты яче­ек в ито­гах, «при­стро­ен­ных» к про­ек­ции спра­ва и снизу, так и рас­стояние ме­ж­ду эти­ми ко­ор­ди­на­та­ми – то есть ко­ли­че­ство яче­ек в ито­гах, оп­ре­де­лен­ных по пол­ным клю­чам, ко­то­рые необ­хо­ди­мо ис­поль­зо­вать для фор­ми­ро­вания ито­гов по частич­ным клю­чам. По­сколь­ку ко­ли­че­ство осей ги­пер­ку­ба, на­кла­ды­вае­мых на ось про­ек­ции, мо­жет быть про­из­воль­ным, то для фор­ми­ро­вания частич­ных клю­чей бу­дем ис­поль­зо­вать век­тор сло­ва­рей: '''QVector&amp;lt;QMap&amp;lt;QString,int&amp;gt;&amp;gt;'''.&lt;br /&gt;
&lt;br /&gt;
Фор­ми­ро­вание ито­гов бу­дем осу­ще­ств­лять при по­мо­щи цик­лов, пе­ре­би­раю­щих ячей­ки мас­си­ва с про­ек­ци­ей ги­пер­ку­ба. А про­бле­му ви­да ито­гов, а имен­но: сум­ма, среднее, мак­си­мум или минимум – бу­дем ре­шать при по­мо­щи вир­ту­аль­ных функ­ций вспо­мо­га­тель­ных клас­сов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
 class Ttl{&lt;br /&gt;
   protected:&lt;br /&gt;
    double r;&lt;br /&gt;
   public:&lt;br /&gt;
    void setR(double R);&lt;br /&gt;
    virtual void updR(double E)=0;&lt;br /&gt;
    virtual double getR(int N)=0;&lt;br /&gt;
 };&lt;br /&gt;
 class Sum: public Ttl{&lt;br /&gt;
   public:&lt;br /&gt;
    virtual void updR(double E);&lt;br /&gt;
    virtual double getR(int N);&lt;br /&gt;
 };&lt;br /&gt;
 class Avg: public Sum{&lt;br /&gt;
   public:&lt;br /&gt;
    virtual double getR(int N);&lt;br /&gt;
 };&lt;br /&gt;
 class Max: public Sum{&lt;br /&gt;
   public:&lt;br /&gt;
    virtual void updR(double E);&lt;br /&gt;
 };&lt;br /&gt;
 class Min: public Sum{&lt;br /&gt;
   public:&lt;br /&gt;
    virtual void updR(double E);&lt;br /&gt;
 };&lt;br /&gt;
 void Ttl::setR(double R){r=R;}&lt;br /&gt;
 void Sum::updR(double E){r+=E;}&lt;br /&gt;
 void Max::updR(double E){if(E&amp;gt;r)r=E;}&lt;br /&gt;
 void Min::updR(double E){if(E&amp;lt;r)r=E;}&lt;br /&gt;
 double Sum::getR(int N){return r;}&lt;br /&gt;
 double Avg::getR(int N){return r/N;}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Име­на у клас­сов го­во­ря­щие, а пред­на­зна­чение функ­ций оче­вид­но и не тре­бу­ет разъ­яснений. Един­ствен­ное, что вы­зы­ва­ет во­прос, так это вир­ту­аль­ные функ­ции. Стои­ло ли бо­роть­ся за эф­фек­тив­ность ко­да, ис­поль­зуя па­ра­мет­ри­зо­ван­ные кон­тейнеры, что­бы по­том все, сэ­ко­ном­лен­ное бу­к­валь­но по мил­ли­се­кун­дам, так без­дар­но спустить в по­следний мо­мент? По­ясним: па­ра­мет­ри­зо­ван­ные кон­тейнеры ис­поль­зу­ют­ся внут­ри цик­лов, сканирую­щих таб­ли­цу с ис­ход­ны­ми дан­ны­ми или ги­пер­куб. Дан­ная таб­ли­ца в ре­аль­ных за­да­чах мо­жет иметь несколь­ко де­сят­ков, а то и со­тен ты­сяч строк. А для мас­си­ва, в ко­то­ром фор­ми­ру­ет­ся про­ек­ция и ито­ги, счет идет на де­сят­ки. Тео­ре­ти­че­ски, конеч­но, мож­но сфор­ми­ро­вать от­чет и на несколь­ко ты­сяч стро­чек и ко­ло­нок, толь­ко кто же его смот­реть бу­дет?&lt;br /&gt;
&lt;br /&gt;
===Фи­наль­ные штри­хи===&lt;br /&gt;
&lt;br /&gt;
Вы­вод про­ек­ции и ито­гов на фор­му и до­бав­ление к ним за­го­лов­ков строк и столб­цов – са­мо­стоя­тель­ная за­да­ча, и в дан­ной ста­тье не рас­смат­ри­ва­ет­ся, на­ря­ду с осталь­ны­ми во­про­са­ми про­ек­ти­ро­вания ин­тер­фей­са с поль­зо­ва­те­лем, а так­же фор­ма­та фай­ла, в ко­то­рый по­ме­ща­ет­ся от­чет, сгенери­ро­ван­ный про­грам­мой. Но в про­грам­ме, ко­то­рую (на­помним) вы най­де­те на LXFDVD, все это сде­ла­но. По­это­му она го­то­ва к ис­поль­зо­ванию «из ко­роб­ки».&lt;br /&gt;
&lt;br /&gt;
Пред­ла­гае­мая ме­то­ди­ка мно­го­мер­но­го ана­ли­за дан­ных, конеч­но, не ог­раничи­ва­ет­ся толь­ко язы­ком ''C++'' и биб­лио­те­кой ''Qt''. Впол­не воз­мож­на реа­ли­за­ция на ''wxWidgets'' с ис­поль­зо­ванием ''STL'', а па­ра­мет­ри­зи­ро­ван­ные шаб­ло­ны име­ют­ся и в язы­ках ''Java'' и ''C#''.&lt;br /&gt;
&lt;br /&gt;
В по­следний мо­мент, про­смат­ри­вая де­мон­ст­ра­ци­он­ную ба­зу дан­ных, мы за­ме­ти­ли, что де­вуш­ки-про­дав­щи­цы про­ра­бо­та­ли у нас по три го­да без от­пус­ков. Да... Луч­ше бы мы взло­ма­ли ба­зу дан­ных си­рот­ско­го при­юта.&lt;/div&gt;</summary>
		<author><name>Crazy Rebel</name></author>	</entry>

	</feed>