• Save
User Aggs In As
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

User Aggs In As

on

  • 725 views

 

Statistics

Views

Total Views
725
Views on SlideShare
725
Embed Views
0

Actions

Likes
0
Downloads
0
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

User Aggs In As Presentation Transcript

  • 1. Пользовательские вычисления в кубах Analysis Services Алексей Шуленин Microsoft
  • 2. Введение
    • С Вашего позволения я не буду сегодня рассказывать, что такое OLAP и для чего он нужен
    • Давайте сразу перейдем к делу
  • 3. Стандартные меры
    • Как Вы знаете...
    • Ячейка, состоящая из нескольких записей таблицы фактов, по умолч. агрегируется одной из след.ф-ций
      • Sum
      • Count
      • Min
      • Max
      • Distinct Count
    • В отличие от пользовательских агрегатов они предвычислены и хранятся в кубе, а не считаются по мере надобности
  • 4. Важное замечание
    • Сказанное не означает, что вычисляются все возможные агрегаты
      • Их полное число ~ е n-1 , где n – размерность куба
        • Доказать самим
      • Поэтому диск быстро кончится
    • На стадии проектирования куба определяются (но не считаются) нужные агрегаты
      • Design Storage Wizard пытается соблюсти баланс между размером и производительностью
      • Эмпирика – в первую очередь те, от к-х за минимальное число операций можно посчитать остальные
      • Потом мн-во агрегатов корректируется на основе типовой нагрузки – Usage-Based Optimization
        • Примерно, как ITW
  • 5. Мера DISTINCT COUNT
    • Работает только по числовым полям
      • В старой документации не отражено
    • Более "тяжелый" случай по сравнению с остальными
    • Как мы знаем, Analysis Service при создании куба считает не все агрегаты
      • Остальные могут досчитываться в ходе выполнения запроса на основе известных
      • Для аддитивных мер не составляет труда посчитать агрегат, напр., уровня года, если известны агрегаты уровня квартала
        • В случае меры SUM Год = SUM(Q1, Q2, Q3, Q4)
        • В случае меры MAX Год = MAX(Q1, Q2, Q3, Q4)
        • И т.д.
      • С DISTINCT COUNT это не проходит
  • 6. Пример
    • Анализируем журнал ISA Server
      • Что и когда посещали пользователи
      • Интересует общее кол-во заходов, так и кол-во уникальных сайтов
    http://msdn.microsoft.com/library/ 207046250121 0x30784346 Александр Гладченко 30.09.2002 19:30 0x30784333 0x30783430 0x30784346 0x30784345 0x30783346 0x30784346 0x30784333 0x30783432 0x30784431 0x30784333 0x30784333 IP_Binary URL IP_BigInt User_ID Time http://www.sql.ru 195209060199 Александр Гладченко 01.10.2002 22:00 http://www.hotsex.com 64239005092 Алексей Шуленин 01.10.2002 19:00 http://www.microsoft.com/sql 207046249027 Александр Гладченко 01.10.2002 17:00 http://www.hardcore.com 206126000001 Алексей Шуленин 01.10.2002 15:00 http://www.sqlmag.com 63088172065 Александр Гладченко 01.10.2002 11:00 http://www.microsoft.com/sql 207046249027 Александр Гладченко 01.10.2002 10:00 http://www.sql.ru 195209060199 Александр Гладченко 01.10.2002 0 9:00 http://www.xxx.com 66028153014 Алексей Шуленин 30.09.2002 19:45 http://www.sex.com 209081007023 Алексей Шуленин 30.09.2002 19:20 http://www.sql.ru 195209060199 Александр Гладченко 30.09.2002 19:10 http://www.sql.ru 195209060199 Александр Гладченко 30.09.2002 19:00
  • 7. Пример
    • Как следствие, увеличивается время процессинга, снижается масштабируемость
      • Весь куб трактуется Analysis Services как неаддитивный
      • Имеет смысл не держать в нем других мер
        • Выносить их в другие кубы и объединять в виртуальные
    • Накладывает на куб дополнительные ограничения
      • Только одна мера такого типа может присутствовать в регулярном кубе
      • В кубе не допускаются измерения с пользовательскими свертками
        • Custom Rollup Operators, Custom Rollup Formulas – см. далее
    • Эти ограничения не касаются виртуальных кубов
    • Либо эмулировать DISTINCT COUNT при пом. Calculated Members
    • Нижние агрегаты не помогают
      • Исключение – измерения, построенные на member properties измерения, по к-му считается DISTINCT COUNT
      • Образуют непересекающиеся куски
        • Напр., регион сайта
      • Поэт. такая агр.ф-ция наз. полуаддитивной
    4 8   2002 Total 3 5 4-й квартал   2 3 3-й квартал 2002 IP_Distinct IP_Count Квартал Год   Data     Александр Гладченко Чел
  • 8. Как посмотреть коллекцию агрегатов
    • DSO.ServerClass olap_server = new DSO.ServerClass();
    • olap_server.Connect("localhost");
    • DSO.DatabaseClass olap_db = (DSO.DatabaseClass) olap_server.MDStores.Item("NW");
    • DSO.CubeClass olap_cube = (DSO.CubeClass) olap_db.Cubes.Item("Продажи");
    • DSO.PartitionClass olap_part = (DSO.PartitionClass) olap_cube.Partitions.Item(1);
    • Console.WriteLine("В дефолтовой партиции куба {0} содержится {1} агрегатов. Вот они:", olap_cube.Name, olap_part.MDStores.Count);
    • foreach (DSO.AggregationClass agg in olap_part.MDStores)
    • Console.Write(agg.Name + " ; ");
    • olap_server.CloseServer();
    • a 1 …a n
      • a i – уровень по i- му измерению
  • 9. Точнее – это множества агрегатов
    • В ROLAP они видны как SELECT ы c GROUP BY по уровням
    • 1142
      • По 4-му уровню 3-го измерения (Время - > Месяц)
      • По 2-му уровню 4-го измерения (Клиент - > Страна)
    • Под 1-м уровнем понимается (All)
  • 10. Структура таблицы агрегатов Имя раздела Имя куба Мера, агрегированная в соотв. с ее ф-цией GROUP BY по членам выбр. уровня
  • 11. Вопрос на понимание
    • Почему по региону она суммировала так:
    • INSERT INTO Продажи_Продажи_03 (Country_L12, Region_L13, SUM_LineItemFreight, ... )
    • SELECT "dbo"."Customer_Dim"."Country" as Country_L12 , "dbo"."Customer_Dim"."Region" as Region_L13, SUM("dbo"."Sales_Fact"."LineItemFreight") As SUM_LineItemFreight, ... FROM "dbo"."Sales_Fact", "dbo"."Customer_Dim"
    • WHERE ("dbo"."Sales_Fact"."CustomerKey"="dbo"."Customer_Dim"."CustomerKey")
    • GROUP BY "dbo"."Customer_Dim"."Country", "dbo"."Customer_Dim"."Region"
    • А по городу так:
    • INSERT INTO Продажи_Продажи_04 (Country_L12, Region_L13, City_L14, SUM_LineItemFreight, ... )
    • SELECT MIN ("dbo"."Customer_Dim"."Country") as Country_L12 , MIN ("dbo"."Customer_Dim"."Region") as Region_L13 , "dbo"."Customer_Dim"."City" as City_L14 , SUM("dbo"."Sales_Fact"."LineItemFreight") As SUM_LineItemFreight, ...
    • FROM "dbo"."Sales_Fact", "dbo"."Customer_Dim"
    • WHERE ("dbo"."Sales_Fact"."CustomerKey"="dbo"."Customer_Dim"."CustomerKey")
    • GROUP BY "dbo"."Customer_Dim"."City"
  • 12. Ответ
    • Найдите 1 существенное отличие:
    • Если ключи на протяжении уровня неуникальны
      • регион – в разных странах есть «Прочие регионы»,
    • то координаты члена - > цепочка с верхнего уровня иерархии
      • GROUP BY Country, Region
    • Если уникальны, то City однозначно определяет своих родителей на верхних уровнях ( Region и Country ) и тянуть их в GROUP BY не нужно
      • MIN – чтобы включить родителей в SELECT; все равно дубликатов гарантированно не будет (при данном City)
  • 13. Последовательность расчета
    • Сначала Analysis Service попробовала создать под агрегаты индексированные представления
      • Почему это лучше, чем таблицы, и что для этого нужно – разбирали на Платформе
      • Обломалась, решила не выпендриваться
    • 3 уровня в Продуктах * 3 уровня в Сотрудниках * 5 уровней во Времени * 5 уровней в Клиенте = 225 агрегатных таблиц
    • Создала всего 39, остальные зажала
      • Чем глубже лезет в младшие измерения, тем более небрежно агрегирует старшие
    • Несмотря на это Design Storage Wizard пишет, что будет достигнуто 100% производительности
      • Вывод: 100% не означает, что будут рассчитаны и положены в куб все возможные агрегаты
    1112 1113 1114 1115 1121 1122 1123 1124 1125 1131 1132 1133 1134 1141 1142 1151 1211 1212 1213 1214 1221 1222 1231 1241 2111 2112 2113 2114 2121 2122
  • 14. Задание принудительной агрегации в измерении
    • При помощи св-ва AggregationUsage интерфейса Dimension
    • Имплементируется в классах ClsCubeDimension ( там оно Read-Write) и ClsPartitionDimension (там оно Read-Only, п.ч. наследуется от куба)
    • Принимает зн-я enum типа DimensionAggUsageTypes
      • 0 = dimAggUsageStandard – как clsAnalyzer на душу положит
      • 1 = dimAggUsageTopOnly – считать агрегаты только для уровня All (= 1)
      • 2 = dimAggUsageDetailsOnly – только для листового уровня
      • 3 = dimAggUsageCustom – c м. след.слайд
      • 4 = dimAggUsageTopAndDetailsOnly – понятно
  • 15. Задание принудительной агрегации в уровне
    • При помощи св-ва EnableAggregations интерфейса Level
    • Имплементируется в классах clsCubeLevel (Read-Write) и clsPartitionLevel ( Read-Only )
    • Если для родительского измерения AggregationUsage = dimAggUsageCustom , то
      • True – рассматривать агрегаты для данного уровня
      • False – нет
  • 16. Последовательность выполнения многомерного запроса
    • Посмотреть, может быть, результат уже содержится в кэше на данном клиенте?
    • Если нет, проверить серверный кэш
    • Если нет, посмотреть, можно ли удовлетворить запрос из имеющихся агрегатов
      • Помним, что заказанные 100% произв-ти не гарантируют 100% агрегатов
      • Помним про semi-additive measures
    • Если нет, то какие агрегаты еще нужно досчитать
      • Помним, что при ROLAP за ними нужно лезть в источник
    • Если агрегатов недостаточно, то взять детальные данные
      • Помним, что при ROLAP и HOLAP за ними нужно лезть в источник
  • 17. Calculated Members
    • Традиционно ассоциируются с вычисляемыми мерами
  • 18. Calculated Members
    • На самом деле может относиться к любому измерению
      • Не обязательно Measures
    • Задается как член, являющийся ребенком регулярного нелистового члена
      • Сам, в свою очередь, не может иметь детей
    • Задается вычисляемым в ходе запроса MDX-выражением
  • 19. Пример
    • Вот измерение «Время»
    Обратите внимание, что уровень «день» не показан - Calc Members не могут создаваться ниже листьев Определяем вычисляемый член под июлем 1996 г.
  • 20. Пример
    • Получили еще один «день» в июле 1996 г.
  • 21. Отличие calc member от member property
    • Member property
      • Не увеличивает (хотя бы фиктивно) число ячеек в кубе
      • Подчиняется не члену-родителю, а уровню в целом
      • Вычисляется не при помощи MDX на основе других ячеек куба, а на основе данных операционного источника в его терминах ( SQL)
    case when (DatePart(year, &quot;dbo&quot;.&quot;Time_Dim&quot;.&quot;TheDate&quot;) % 4 = 0 and DatePart(year, &quot;dbo&quot;.&quot;Time_Dim&quot;.&quot;TheDate&quot;) % 100 <> 0) or DatePart(year, &quot;dbo&quot;.&quot;Time_Dim&quot;.&quot;TheDate&quot;) % 1000 = 0 then 366 else 365 end
  • 22. Создание calc member
    • Масштаба запроса
      • WITH MEMBER … AS ‘MDX- выражение ’
    • Масштаба сессии
      • CREATE MEMBER … AS аналогично
    • Масштаба куба
      • Через DSO – см. след. слайд
  • 23. Создание calc member ... DSO.CubeClass olap_cube = (DSO.CubeClass) olap_db.Cubes.Item(&quot;Продажи&quot;); string CalcMemberName = &quot;Новый член&quot;; try { DSO.CubeCommandClass olap_cmd = (DSO.CubeCommandClass) olap_cube.Commands.Item(CalcMemberName); if (olap_cmd.CommandType == DSO.CommandTypes.cmdCreateMember) olap_cube.Commands.Remove(CalcMemberName); } catch (NullReferenceException e) {} finally { DSO.CubeCommandClass olap_cmd = (DSO.CubeCommandClass) olap_cube.Commands.AddNew(CalcMemberName, DSO.SubClassTypes.sbclsRegular); olap_cmd.CommandType = DSO.CommandTypes.cmdCreateMember; olap_cmd.Statement = &quot;CREATE MEMBER CURRENTCUBE.[Время].[Год].&[1996].&[3].&[7].[&quot; + CalcMemberName + &quot;] AS '[Время].CurrentMember.Parent.Name'&quot;; olap_cube.Update(); } olap_server.CloseServer();
  • 24. Multicolumn measures
    • Не обязательно прибегать к calc members , если агрегат задействует несколько колонок таблицы фактов
      • В выражении - только арифметические операторы +, -, *, /
      • Вообще странно, что не понимает произвольного валидного в терминах операционного источника выражения
    • Можно обойтись стандартной мерой
  • 25. Дополнительные свойства Calculated Members по сравнению с мерами
    • FORMAT_STRING, FORE_COLOR, BACK_COLOR, FONT_NAME, FONT_SIZE, …
    • Оцениваются динамически
    • Позволяют навести дополнительные красивости в отчетах централизованно на уровне сервера
      • Если, конечно, клиент в курсе этих св-в
    • Пример:
      • with member Measures.[Рост продаж] as '([Measures].[Store Sales], Time.CurrentMember) - ([Measures].[Store Sales], Time.PrevMember)', FORE_COLOR = 'iif (Measures.[Рост продаж] < 0, rgb(255, 0, 0), rgb(0, 255, 0))', FORMAT_STRING = '#,#.00'
      • select Time.Members on rows, Store.[USA].Children on columns
      • from Sales where Measures.[Рост продаж]
      • CELL PROPERTIES FORE_COLOR, FORMATTED_VALUE
  • 26. Более сложный пример
    • Если в целом по региону рост нормальный, но внутри есть потомки с отрицательным ростом, красить фон в желтый
      • Обсуждение MDX не входит в цели доклада
    with member Measures.[Рост продаж] as '([Measures].[Store Sales], Time.CurrentMember) - ([Measures].[Store Sales], Time.PrevMember)', FORE_COLOR = 'iif (Measures.[Рост продаж] < 0, rgb(255, 0, 0), rgb(0, 255, 0))', BACK_COLOR = 'iif (Count(Filter(Descendants(Store.CurrentMember, [Store City], SELF_AND_BEFORE), Measures.[Рост продаж] < 0)) > 0, rgb(255, 255, 0), rgb(255, 255, 255))' , FORMAT_STRING = '#,#.00' select Time.Members on rows, Descendants(Store.USA, [Store City], SELF_AND_BEFORE) on columns from Sales where Measures.[Рост продаж] CELL PROPERTIES FORE_COLOR, BACK_COLOR , FORMATTED_VALUE
  • 27. Custom Rollup Formula
    • Отменяет действие агрегатной функции меры и агрегирует детей по данной иерархии в соответствии с MDX-выражением в формуле
    Год - стандартная агрегация (сумма) Квартал – не сумма месяцев, а остаток за последний месяц
  • 28. Custom Rollup Formula
    • Применяется ко всем членам уровня
      • Квартал - > Q1, Q2, Q3, Q4
      • Если исключения, то iif:
        • iif(Time.CurrentMember.Name = &quot;Q1&quot;, 0, Time.CurrentMember.LastChild)
    • Если определено для shared dimension, то действует во всех кубах, где оно участвует
      • Можно отредактировать формулу свертки в измерении непосредственно для данного куба
        • Cube Editor
      • Т.е. для clsCubeDimension, а не clsDatabaseDimension
  • 29. Unary Operators
    • С какими знаками члены агрегируются в своего родителя
    • В реляц.табл. соотв.поле, откуда берутся знаки для членов
  • 30. Unary Operators
    • Типичный пример измерения – счета
      • + - активы, - - пассивы, ~ - внебалансовые
    • В случае некоммутативных операций
      • Напр., у одного члена +, у брата *
    • порядок в соответствии с order by уровня
  • 31. Custom Member
    • Идея – аналогично Unary Operators, функционал – шире
    • Вместо унарного оператора – MDX-формула, в соответствии с к-й получается значение данного члена
    • MDX, к-й будет применяться к первичному значению, также берется из строкового поля реляц.таблицы
  • 32. Calculated Cells
    • MDX- формула, применяемая к более общим областям куба
    • Calculation Subcube задается в виде набора измерений, каждое из которых ограничивается одним из след.способов – см.рис.
      • Custom MDX должен сводиться к одному из вышестоящих вариантов
  • 33. Calculated Cells
    • Calculation Condition позволяет дополнительно оговорить диапазон вычислений
      • Что удобно для более тонкой фильтрации Subcube
    • Собственно, формула вычислений для заданной области ячеек
  • 34. Пример
    • Применим формулу, аналогичную рассмотренной в Custom Rollup только к
      • Продажам в штуках
      • штату Вашингтон (включая отнсящиеся к нему города, но не расположенные в них торговые точки)
      • Годам и первым двум кварталам в каждом году
    with cell calculation Calc1 for '({Measures.[Unit Sales]}, DESCENDANTS(Store.[Store State].[WA], Store.[Store City]))' as 'Time.CurrentMember.FirstChild', condition = 'Time.CurrentMember.Level.Name = &quot;Year&quot; or Time.CurrentMember.Level.Name = &quot;Quarter&quot; and (Time.CurrentMember.Name = &quot;Q1&quot; or Time.CurrentMember.Name = &quot;Q2&quot;)' select Time.Members on rows, CrossJoin(Store.[USA].Children, {Measures.[Unit Sales], Measures.[Store Sales]}) on columns from Sales
  • 35. Пример
    • Видим, что все работает:
    • В 1997 г. и в 1-м и 2-м кварталах по мере Unit Sales сидит действительно цифра от FirstChild
    • По всем остальным областям (мере Store Sales, 3-му и 4-му кварталам) – по умолчанию (дети суммируются)
  • 36. Взаимодействие пользовательских вычислений
    • Что происходит, когда в одной ячейке сталкиваются
      • Разные типы пользовательских вычислений
        • Напр., Custom Rollup и Custom Member
      • Два однотипных вычисления по разным осям
        • Напр., два Calculated Members
  • 37. Понятие SOLVE ORDER
    • Пример
      • CurrentMember везде можно опустить – просто, чтобы было понятно, что участвуют 2 измерения (как минимум)
    with member Measures.[Прибыль] as '(Time.CurrentMember, [Measures].[Store Sales]) - (Time.CurrentMember, [Measures].[Store Cost])', format_string = '#,#.00' member Time.[Прирост в 4 кв.] as '(Time.[Q4], Measures.CurrentMember) / (Time.[Q3], Measures.CurrentMember)', format_string='#,#.000' select {Measures.[Store Cost], Measures.[Store Sales], Measures.[Прибыль]} on columns, {Time.[Q3], Time.[Q4], Time.[Прирост в 4 кв.]} on rows from Sales Здесь Доходы - Издержки Здесь 4-й кв-л / 3-й кв-л А здесь-то что: - столбцов или / строк ??? 1.300 1.303 Прирост 34219.51 56965.64 22746.13 Q4 26362.85 43825.97 17463.12 Q3 Прибыль Sales Cost
  • 38. Понятие SOLVE ORDER
    • Побеждает 2-я формула
    • Побеждает 1-я формула
    with member Measures.[Прибыль] as '[Measures].[Store Sales] - [Measures].[Store Cost]', format_string = '#,#.00', solve_order = 1 member Time.[Прирост в 4 кв.] as 'Time.[Q4] / Time.[Q3]', format_string='#,#.000' , solve_order = 2 select {Measures.[Store Cost], Measures.[Store Sales], Measures.[Прибыль]} on columns, {Time.[Q3], Time.[Q4], Time.[Прирост в 4 кв.]} on rows from Sales with member Measures.[Прибыль] as '[Measures].[Store Sales] - [Measures].[Store Cost]', format_string = '#,#.00', solve_order = 2 member Time.[Прирост в 4 кв.] as 'Time.[Q4] / Time.[Q3]', format_string='#,#.000' , solve_order = 1 select {Measures.[Store Cost], Measures.[Store Sales], Measures.[Прибыль]} on columns, {Time.[Q3], Time.[Q4], Time.[Прирост в 4 кв.]} on rows from Sales 1.298 1.300 1.303 Прирост 34219.51 56965.64 22746.13 Q4 26362.85 43825.97 17463.12 Q3 Прибыль Sales Cost .00 1.300 1.303 Прирост 34219.51 56965.64 22746.13 Q4 26362.85 43825.97 17463.12 Q3 Прибыль Sales Cost
  • 39. Понятие SOLVE ORDER
    • Solve Order можно видеть и менять только для Calculated Members и Calculated Cells
      • Таким образом, для них столкновение интересов разрешается при помощи Solve Order
    • У всех остальных типов рассмотренных пользовательских агрегаций он недоступен
      • Можно считать, что он < 0, поэтому они заведомо проигрывают calc members и cells
    • Если на одну ячейку приходится Custom Rollup (Rollup Formula или дети с унарными операторами) и Custom Member
      • Выигрывает Custom Member Formula
    • Если ячейка имеет Rollup Formula , а дети – Unary Operators
      • Выигрывает Rollup Formula
  • 40. Однотипные вычисления по разным осям
    • Т.е. если Solve Order одинаковый
    • Выигрывает последняя ось в кубе
      • Этот порядок можно менять
      • Куб после этого придется перепроцессить
    • Т.е. можно считать, что чем каждая ось немного добавляет к Solve Order
  • 41. Понятие CALCULATION PASS
    • Пример 1
      • Сделать область вычисляемых ячеек, в которой значение каждой ячейки удваивается
      • Первое, что приходит на ум:
        • with cell calculation Calc1 for '({Measures.[Unit Sales]})' as 'Measures.[Unit Sales] * 2'
        • select Time.Members on rows, Store.[USA].Children on columns from Sales where Measures.[Unit Sales]
      • Что немедленно дает ошибку Infinite recursion detected during execution of calculated member
      • Чтобы избежать зацикливания, необходимо брать значение с предыдущего шага вычислений
        • with cell calculation Calc1 for '({Measures.[Unit Sales]})' as ' CalculationPassValue(Measures.[Unit Sales], -1, RELATIVE) * 2'
        • select Time.Members on rows, Store.[USA].Children on columns from Sales where Measures.[Unit Sales]
  • 42. Понятие CALCULATION PASS
    • Пример 2
      • Измерения Parent-Child с опцией Non-leaf data hidden
      • Когда данные на узлах не агрегируются с нижних уровней, а берутся напрямую из источника (как листья)
    • В этом случае Rollup Formula уровня неявно получает следующий вид
      • CalculationPassValue( Employees .CurrentMember.DataMember, 0)
  • 43. Номер прохода
    • Итак, имеем ту же вводную, что и для SOLVE ORDER – несколько формул на одну ячейку
      • SOLVE ORDER назначает победителя, отвергая остальных
      • CALCULATION PASS позволяет применить несколько вычислений к одной ячейке и установить порядок их выполнения
    • CALCULATION PASS = 0
      • Извлечение данных из источников, расчет custom members и calculated members
    • CALCULATION PASS = 1
      • Агрегирование: вычисления унарных операторов членов и rollup- формул
    • Менять значение CALCULATION PASS можно только у Calculated Cells
      • 1 (по умолчанию) и выше
  • 44. Пример
    • select DrilldownLevel({Time.[1997]}) on rows, {Customers.[All Customers]} on columns from Sales where Measures.[Store Sales]
    • Пусть хотим сделать
      • Q3 = 2 * Q4
      • Q4 = 2 * Q3
    • with cell calculation Calc_Q3 for '({Measures.[Store Sales]}, {Time.[1997].[Q3]})' as 'CalculationPassValue((Time.[Q4], Measures.[Store Sales]), -1, RELATIVE) * 2'
    • cell calculation Calc_Q4 for '({Measures.[Store Sales]}, {Time.[1997].[Q4]})' as 'CalculationPassValue((Time.[Q3], Measures.[Store Sales]), -1, RELATIVE) * 2'
    • select …
    152 671.62 Q4 140 271.89 Q3 132 666.27 Q2 139 628.35 Q1 565 238.13 1997 All Customers
  • 45. Пример
    • Теперь слегка изменим пример
      • with cell calculation Calc_Q3 for '({Measures.[Store Sales]}, {Time.[1997].[Q3]})' as 'CalculationPassValue((Time.[Q4], Measures.[Store Sales]), -1, RELATIVE) * 2', calculation_pass_number = 1
      • cell calculation Calc_Q4 for '({Measures.[Store Sales]}, {Time.[1997].[Q4]})' as 'CalculationPassValue((Time.[Q3], Measures.[Store Sales]), -1, RELATIVE) * 2', calculation_pass_number = 2 ...
    • Шаг 0
    • Шаг 1
    * 2 280 543.78 Q4 305 343.24 Q3 132 666.27 Q2 139 628.35 Q1 858 181.64 1997 All Customers 152 671.62 Q4 140 271.89 Q3 132 666.27 Q2 139 628.35 Q1 565 238.13 1997 All Customers
  • 46. Оценка и вычисление
    • Вопрос
      • Почему поменялась сумма в 1997?
      • Ведь раньше говорилось, что все агрегаты считаются не позже 1-го шага?
    • Потому что оценка и вычисление ячейки – это разные вещи
      • Оценка начинается с максимального Pass Number и идет вниз, запоминая, от каких ячеек зависит данная
      • На шаге 0 получает первичные значения и поднимается обратно вверх, вычисляя значения и разрешая ссылки
      • Рассмотрим на примере единственной ячейки
    • Шаг 0
    • Шаг 1
    * 2
    • Шаг 2
    * 2 280 543.78 Q4 305 343.24 Q3 132 666.27 Q2 139 628.35 Q1 858 181.64 1997 All Customers 152 671.62 Q4 140 271.89 Q3 132 666.27 Q2 139 628.35 Q1 565 238.13 1997 All Customers 610 686.48 Q4 305 343.24 Q3 132 666.27 Q2 139 628.35 Q1 1 188 324.34 1997 All Customers
  • 47. Пример
    • with cell calculation Test for '({Measures.[Sales Count]}, {Time.[1997].Q1}, {Store.USA.WA.Seattle}, {Product.Drink.[Alcoholic Beverages].[Beer and Wine].Wine.Portsmouth.[Portsmouth Chardonnay]})' as 'CalculationPassValue(Measures.[Sales Count], -1, RELATIVE) * 2', calculation_pass_number = 5, calculation_pass_depth = 3
    • select DrilldownLevel({Time.[1997]}) on rows, {Store.USA.WA.Seattle} on columns from Sales where (Measures.[Sales Count], Product.Drink.[Alcoholic Beverages].[Beer and Wine].Wine.Portsmouth.[Portsmouth Chardonnay])
      • calculation_pass_depth – сколько шагов отмотать назад, чтобы оценить выражение
    2 Q4 2 Q3 1 Q2 1 Q1 6 1997 Seattle
  • 48. Что происходит
    • Оценка
    • Вычисление
    Шаг 4 Шаг 5 Шаг 3 Шаг 0 1 Q1 Seattle 2 * Q1 Seattle 2 * Q1 Seattle 2 Q1 Seattle 4 Q1 Seattle 8 Q1 Seattle 2 * Q1 Seattle
  • 49. Вопросы?
  • 50.