Запрос MDX для линейного графика PerformancePoint
У меня проблемы с получением правильной линейной диаграммы в PerformancePoint с помощью Dashboard Designer на основе пользовательского запроса MDX.
Мы пытаемся отобразить последние 6 месяцев текущего года по сравнению с тем же 6-месячным периодом прошлого года. Я написал запрос, и он возвращает данные, которые мы ожидаем.
SELECT NONEMPTY([Invoice Date].[Fiscal Week of Year].[Fiscal Week of Year])
ON COLUMNS
,NONEMPTY({[Invoice Date].[Hierarchy].[Fiscal Year]
* [Measures].[Amount]}) ON ROWS
FROM [Sales]
Это возвращает правильные данные.
Мы создаем линейную диаграмму для отображения данных. Мы получаем [Сумма] (в долларах) по оси Y и Неделю года. Неделя года - это, по сути, просто числа, поэтому номер текущей недели равен 22 (потому что мы используем не календарный финансовый год). Затем у нас есть временной ряд на основе года, который позволяет нам просматривать номера 22-й недели этого года по сравнению с 22-й неделей предыдущего года.
Наша проблема в том, что последние 6 месяцев пересекают "границу" года. И из-за этого наша ось X не имеет "правильного" хронологического вида. Наша нижняя ось выглядит так (я упростила количество недель):
1 | 2 | 3 |... | 20 | 21 | 22 | 48 | 49 | 50 | 51 | 52 |
Обратите внимание на скачок между 22 и 48. Это численно правильно, однако хронологически этот график должен быть:
48 | 49 | 50 | 51 | 52 | 1 | 2 | 3 |... | 20 | 21 | 22 |
Я знаю, почему это происходит. Финансовая неделя года не является частью нашей иерархии [Дата выставления счета].
Нашей иерархией был финансовый год => Финансовый квартал => Финансовый месяц => Финансовая дата
Итак, мы исправили это и добавили неделю в иерархию
Финансовый год => Финансовый квартал => Финансовый месяц => Финансовая неделя года => Финансовая дата
И новый запрос MDX выглядит так:
SELECT NONEMPTY([Invoice Date].[Hierarchy].[Fiscal Week of Year])
ON COLUMNS
,NONEMPTY({[Invoice Date].[Fiscal Year].[Fiscal Year]
* [Measures].[Amount]}) ON ROWS
FROM [Sales]
Что ж, это решило нашу проблему сортировки, потому что теперь Неделя года имеет контекст относительно того, к какому году относится Неделя 22... но это представляет другую проблему
Из-за этого нового контекста наш график теперь не будет перекрывать два разных временных ряда и вместо этого будет представлять их в виде спины, потому что они больше не разделяют простое число, у них теперь есть год + неделя (даже если на диаграмме только отображаются номер недели)
Таким образом, график теперь выглядит следующим образом
48 | 49 | 50 | 51 | 52 | 1 | 2 | 3 | ... | 20 | 21 | 22 |48 | 49 | 50 | 51 | 52 | 1 | 2 | 3 | ... | 20 | 21 | 22 |
Обратите внимание на то, что сортировка является правильной в хронологическом порядке, но теперь по оси X бок о бок выходит сумма в два года.
Надеюсь, это многословное объяснение поможет объяснить проблему. Кажется, что у нас может быть либо перекрывающийся временной ряд с "неправильным" видом, ИЛИ мы можем иметь правильный вид с неделями, но теряем способность сравнивать год за годом.
Я хочу, чтобы мы получили правильную сортировку, поэтому:
48 | 49 | 50 | 51 | 52 | 1 | 2 | 3 |... | 20 | 21 | 22 |
Но все же быть в состоянии иметь два разных года пересечения друг с другом.
Или, другими словами, я хочу, чтобы неделя года сортировалась по году, а затем "забывала" этот контекст при возврате данных, чтобы линейная диаграмма позволяла перекрывать недели числом. Я в тупик, как это осуществить.
2 ответа
Хорошо, у меня есть ответ на вопрос. Следующий запрос MDX вернет значение [Сумма] с финансовыми годами в строках, и в каждом столбце будет указана неделя года. Неделя года будет "отсортирована" по тому, как недели происходят в хронологическом порядке. Это действительно ужасное описание, лучше увидеть его.
WITH SET [Weeks] AS
EXTRACT([Invoice Date].[Dashboard Hierarchy].[Fiscal Week of Year], [Invoice Date].[Dashboard Hierarchy])
SET [Week of Year] AS
INTERSECT(STRTOSET("{" + GENERATE( [Weeks]
,"[Invoice Date].[Fiscal Week Of Year].&[" + [Weeks].CURRENT.NAME + "]"
,",") + "}"), [Invoice Date].[Fiscal Week Of Year].MEMBERS)
SELECT [Week of Year] ON COLUMNS
,{([Invoice Date].[Fiscal Year].[Fiscal Year], [Measures].[Amount])} ON ROWS
FROM [Sales]
Когда вы выполните запрос, вы получите следующие результаты:
Обратите внимание, что столбцы 51, 52, 53, 1, 2, 3, что соответствует диапазону данных, которые я выбрал (от 6 месяцев до даты). Так, в моем примере 6 месяцев назад была 51-я неделя этого года.
Также обратите внимание, что есть данные, которые перекрываются на 51 неделе как для 2012, так и для 2013. Это важно, если вы хотите, чтобы линейный график в содержимом PerformancePoint фактически сравнивал эти точки данных. Вот итоговый график.
Вот что делает запрос
WITH SET [Weeks] AS
EXTRACT([Invoice Date].[Dashboard Hierarchy].[Fiscal Week of Year], [Invoice Date].[Dashboard Hierarchy])
Эта функция использует функцию извлечения для удаления всех членов уровня "Неделя года" из иерархии "Дата". Это возвращает набор, который можно использовать в следующем вычисляемом элементе.
INTERSECT(STRTOSET("{" + GENERATE( [Weeks]
,"[Invoice Date].[Fiscal Week Of Year].&[" + [Weeks].CURRENT.NAME + "]"
,",") + "}"), [Invoice Date].[Fiscal Week Of Year].MEMBERS)
Здесь происходит большая часть работы. Таким образом, начиная с "изнутри" и работая наш путь.
Функция Generate генерирует разделенную запятыми строку на основе ранее созданного вычисляемого члена Weeks. Эта строка фактически создается так, чтобы выглядеть как элемент [Fiscal Week of Year], который содержит только недели и не является частью иерархии дат. Это важно, потому что вы не можете вернуть недели как часть иерархии в линейный график, или это не позволит 51-й неделе, например, с 2012 по 2013 годы перекрываться, потому что они разные участники.
Затем новая строка, разделенная запятыми, преобразуется в набор с помощью функции StrToSet.
Наконец, что не менее важно, потому что может быть несколько недель 51, например, я пересекаю результаты, чтобы получить уникальный список.
Новый вычисляемый член Week of Year затем возвращается НА КОЛОННЫ.
Я всегда открыт для предложений о том, как выполнить то же самое, но проще, потому что кажется, что я создал запрос Rube Goldberg MDX, но я просто не смог найти ни одного примера во всех интернетах о том, как выполнить это.
Я вижу два возможных решения: либо оставить исходные "года без недель" и применить к ним порядок, либо перейти ко второму решению, сохраняя только самые последние недели в результате запроса и ссылаясь на недели предыдущих лет в расчете.
Первое решение будет работать следующим образом (я использовал куб Microsoft Adventure Works, а с ноября 2007 г. по февраль 2008 г.):
SELECT Extract(
(
[Date].[Calendar].[Month].&[2007]&[11] : [Date].[Calendar].[Month].&[2008]&[2]
)
* [Date].[Calendar Week of Year].[Calendar Week of Year].members
, [Date].[Calendar Week of Year])
on COLUMNS,
[Date].[Calendar].[Calendar Year].Members
on ROWS
FROM [Adventure Works]
WHERE [Measures].[Internet Sales Amount]
Второй будет работать следующим образом:
WITH Member [Measures].[PrevYearAmount] as
(
ParallelPeriod([Date].[Calendar Weeks].[Calendar Year], 1, [Date].[Calendar Weeks].CurrentMember),
[Measures].[Internet Sales Amount]
)
SELECT [Date].[Calendar Weeks].[Calendar Week].&[44]&[2007] : [Date].[Calendar Weeks].[Calendar Week].&[10]&[2008]
on COLUMNS,
{
[Measures].[Internet Sales Amount],
[Measures].[PrevYearAmount]
}
on ROWS
FROM [Adventure Works]
и вместо WITH
предложение, вы можете, конечно, использовать вычисляемый куб, если вы предпочитаете.