Автор: Mosha Pasumansky
Дата публикации оригинала: 2008-09-01
Источник: Блог Mosha Pasumansky

Drillthrough – это отличная особенность Analysis Services, но она имеет ограничения – drill through можно применить только к ячейкам без вычислений. Это автоматически приводит к невозможности выполнения операций drill through на вычисляемых элементах, в общем, и вычисляемых мерах, в частности. Это ограничение было предметом широких дебатов на формуах и в блогах. Оно было занесено в журнале на connect-сайте как предложение “Enable drillthrough on calculated measures”, где оно получило сильную поддержку. А конкуренты также борются с подобными проблемами.

Пока не существует универсального решения этой проблемы, в данной статье мы покажем, как много практических частных случаев могут быть решены в AS 2005. Для начала давайте определим, что значит drill through на вычисляемых мерах. Согласно определению:

«Drillthrough это операция, в которой пользователь указывает отдельную ячейку и сервер аналитики возврщает наиболее детальные данные, которые внесли вклад в данную ячейку».

Для обычных ячеек очень просто показать, что детальные данные относятся именно к ним, но в общем случае это может оказаться очень сложным. Необходимо провести обратное проектирование формулы вычисления, определить зависимости и затем спустится к детальным данным для каждой из них. Однако, в некоторых случаях простых вычислений такие зависимости очевидны. Давайте рассмотрим вычисляемую меру [Intrenet Gross Profit] из куба Adventure Works. Она определена следующим образом:

Create Member CurrentCube.[Measures].[Internet Gross Profit]
AS [Measures].[Internet Sales Amount] - [Measures].[Internet Total Product Cost],
Format_String = "Currency";

Ясно, что [Internet Gross Profit] вычисляется из двух реальных мер - [Internet Sales Amount] и [Internet Product Cost]. Однако как бы мы не передали выражение на вычисляемой мере, это не имеет значения, выражение DRILLTHROUGH приводит к ошибке. Хитрость в том, чтобы построить DRILLTHROUGH-выражение, которое перенаправляется от вычисляемой меры к реальным мерам, из которых она рассчитывается. Ниже показаны точные шаги для достижения этой цели:

  1. Определить новое действие (action). Заметьте, это не может быть drillthrough-действие, т.к. оно даже не может быть применено к вычисляемой мере. Обычное действие.
  2. Установите свойство «Action Target» в значение «Cell» - в конце концов, drillthrough выполняется над ячейками.
  3. Так как свойство «Target Object» для действий над ячейками всегда будет «All cells», мы используем условие для ограничения нашего действия до желаемой вычисляемой меры. В свойстве «Condition» необходимо указать следующее выражение:
    Measures.CurrentMember IS [Measures].[Internet Gross Profit]
  4. Свойство «Action Type» должно быть установлено в значение «Rowset», т.к. drillthrough возвращает набор строк (rowset).
  5. Установите свойство «Caption» в значение «Drillthrough», таким образом, интерфейс клиентского приложения покажет именно этот заголовок, и он будет понятен для пользователя.
  6. Свойство «Action Expression» является наиболее важным. Здесь нам необходимо построить MDX-выражение DRILLTHROUGH, которое выполнит перенаправление к двум реальным мерам. MDX-выражение «DRILLTHROUGHT» не допускает появления в выражении SELECT нескольких ячеек. Каким же образом получить две меры? Мы будем использовать то обстоятельство, что обе меры принадлежат одной и той же группе мер. И вместо того, чтобы помещать их в выражение SELECT, мы отправим их в выражение RETURN. Построение пользовательского выражения RETURN имеет дополнительный плюс в гибкости – можно указать, какие атрибуты будут показаны в результате drillthrough. По умолчанию появятся все атрибуты гранулярности группы мер, но мы можем указать больше или меньше атрибутов. Также мы принимаем решение о реальном содержании этих атрибутов – хотим ли мы ключи, названия, уникальные названия и т.п. Ниже представлено, как может выглядеть выражение RETURN:

    RETURN
    [Internet Sales].[Internet Sales Amount]
    ,[Internet Sales].[Internet Total Product Cost]
    ,NAME([$Date].[Date])
    ,NAME([$Customer].[Customer])
    ,NAME([$Product].[Product])
    ,NAME([$Promotion].[Promotion])
    ,NAME([$Source Currency].[Source Currency Code])
    ,NAME([$Sales Reason].[Sales Reason])

Для того чтобы в операции drillthrough адресоваться к правильной ячейке, мы должны поместить координаты текущей ячейки в выражение SELECT. Одним способом сделать это будет написание длинного MDX-выражения, полученного путем конкатенации строк с использованием подвыражения .CurrentMember.UniqueName для каждой иерархии в кубе. Однако это трудоемкий и ведущий к ошибкам подход. Могут существовать сотни иерархий, новые могут добавляться, старые удаляться или переименовываться. Вместо этого мы можем всего лишь вызвать хранимую процедуру, которая перечислит все текущие координаты (обратите внимание, что мы также могли бы сделать то же самое в выражении RETURN).

Вообще-то, в Analysis Services (ASSP) есть некоторые хранимые процедуры, которые очень похожи на то, что нам здесь нужно, в классе FindCurrentMembers. Похоже, но не точно то, что нам нужно. В нашем конкретном случае мы хотим пропустить меры (мы их жёстко прописываем), и также для краткости нам надо рассмотреть только иерархии атрибутов. Ниже представлен код для достижения этой цели:

public static string CurrentCellAttributes()
{
// start with empty string
string coordinate = String.Empty;
bool first = true;
foreach (Dimension d in Context.CurrentCube.Dimensions)
{
// skip measures
if (d.DimensionType == DimensionTypeEnum.Measure)
continue;

foreach (Hierarchy h in d.AttributeHierarchies)
{
// skip user hierarchies - consider attribute and parent-child hierarchies
// (parent-child is both user and attribute hierarchy)
if (h.HierarchyOrigin == HierarchyOrigin.UserHierarchy)
continue;
if (!first)
coordinate += ",";
first = false;
coordinate += h.CurrentMember.UniqueName;
}
}

return coordinate;
}

Теперь, вооружившись этой мощной процедурой, мы можем построить наше выражение для действия (acion).

"DRILLTHROUGH MAXROWS 100 SELECT (" +
ASSP.ASStoredProcs.FindCurrentMembers.CurrentCellAttributes()
+ ") ON 0 FROM [Adventure Works]
RETURN
[Internet Sales].[Internet Sales Amount]
,[Internet Sales].[Internet Total Product Cost]
,NAME([$Date].[Date])
,NAME([$Customer].[Customer])
,NAME([$Product].[Product])
,NAME([$Promotion].[Promotion])
,NAME([$Source Currency].[Source Currency Code])
,NAME([$Sales Reason].[Sales Reason])
"

Готово! Теперь, если мы внедрим это действие, то в любом клиенте, поддерживающем действия (например, Excel 2007 или cube browser), после нажатия на правую кнопку мыши на ячейке над вычисляемой мерой [Internet Gross Profit] мы увидим дополнительный элемент меню «Drillthrough». Выбрав его, мы перейдём на наиболее детальный уровень данных, которые внесли вклад в эту ячейку.


Для удобства отслеживания новых публикаций рекомендуем подписаться на рассылку или на канал RSS.

Читайте также: