logo
Фёдор Самородов  Преподаватель специального назначения
О проекте Просмотр Уровни подписки Фильтры Обновления проекта Контакты Поделиться Метки
Все проекты
О проекте
Учебные материалы по работе с данными и смежным темам для ИТ-специалистов.
Хранение, обработка и анализ данных на пределе возможностей.
Публикации, доступные бесплатно
Уровни подписки
Единоразовый платёж

Безвозмездное пожертвование без возможности возврата. Этот взнос не предоставляет доступ к закрытому контенту.

Помочь проекту
Уровень 1 500₽ месяц 5 100₽ год
(-15%)
При подписке на год для вас действует 15% скидка. 15% основная скидка и 0% доп. скидка за ваш уровень на проекте Фёдор Самородов

Доступ к платным материалам.

Оформить подписку
Фильтры
Обновления проекта
Контакты
Поделиться
Читать: 5+ мин
logo Фёдор Самородов

Отключайте неработающие связи между размерностями и мерами

Современная ‎методология‏ ‎проектирования ‎многомерных ‎баз ‎данных ‎подталкивает‏ ‎нас ‎к‏ ‎объединению‏ ‎в ‎одном ‎кубе‏ ‎как ‎можно‏ ‎большего ‎количества ‎разных ‎групп‏ ‎мер‏ ‎и ‎измерений.‏ ‎Одним ‎из‏ ‎побочных ‎эффектов ‎такой ‎консолидации ‎является‏ ‎всё‏ ‎более ‎и‏ ‎более ‎разреженная‏ ‎матрица ‎связей ‎между ‎размерностями ‎и‏ ‎группами‏ ‎мер.

Работая‏ ‎с ‎многомерными‏ ‎базами ‎данных,‏ ‎вы ‎наверняка‏ ‎наблюдали‏ ‎такой ‎эффект,‏ ‎когда ‎мера ‎не ‎делится ‎по‏ ‎некоторым ‎измерениям.

Вот‏ ‎я‏ ‎пытаюсь ‎разложить ‎показатели‏ ‎розничных ‎продаж‏ ‎по ‎реселлерам:

Но ‎ни ‎количество‏ ‎проданных‏ ‎единиц ‎товара,‏ ‎ни ‎выручка‏ ‎не ‎распадаются ‎на ‎слагаемые.

Такой ‎же‏ ‎результат‏ ‎я ‎наблюдаю,‏ ‎подключившись ‎к‏ ‎базе ‎из ‎экселя:

В ‎этом ‎нет‏ ‎ничего‏ ‎странного,‏ ‎потому ‎что‏ ‎я ‎пытаюсь‏ ‎проделать ‎некорректную‏ ‎операцию.‏ ‎Если ‎заглянуть‏ ‎в ‎структуру ‎куба, ‎то ‎мы‏ ‎увидим, ‎что‏ ‎размерность‏ ‎реселлеров ‎вообще ‎никак‏ ‎не ‎связана‏ ‎с ‎розничными ‎продажами. ‎Срезы‏ ‎по‏ ‎реселлерам ‎и‏ ‎их ‎атрибутам‏ ‎имеют ‎смысл ‎при ‎анализе ‎оптовых‏ ‎продаж.‏ ‎А ‎прикладывать‏ ‎их ‎к‏ ‎рознице ‎нет ‎никакого ‎смысла. ‎Поэтому‏ ‎сервер‏ ‎и‏ ‎не ‎может‏ ‎разложить ‎розничные‏ ‎меры ‎по‏ ‎значениям‏ ‎чисто ‎оптового‏ ‎атрибута ‎Reseller.[Business ‎Type].

В ‎таких ‎ситуациях‏ ‎сервер ‎принудительно‏ ‎схлопывает‏ ‎не ‎связанные ‎с‏ ‎мерами ‎иерархии‏ ‎до ‎вамого ‎верхнего ‎уровня.‏ ‎Из-за‏ ‎этого ‎в‏ ‎результате ‎запроса‏ ‎итоговое ‎значение ‎просто ‎дублируется.

Хорошо, ‎что‏ ‎мы‏ ‎помним, ‎как‏ ‎устроены ‎наши‏ ‎кубы ‎и ‎не ‎будем ‎пытаться‏ ‎в‏ ‎запросах‏ ‎резать ‎меры‏ ‎по ‎несуществующим‏ ‎связям. ‎Однако,‏ ‎отсутствие‏ ‎сообщения ‎об‏ ‎ошибке ‎или ‎какого-то ‎предупреждения ‎означает,‏ ‎что ‎пользователи‏ ‎время‏ ‎от ‎времени ‎будут‏ ‎пытаться ‎строить‏ ‎некорректные ‎отчёты ‎и ‎тратить‏ ‎время‏ ‎на ‎поиск‏ ‎ошибок.

В ‎конструкторе‏ ‎куба ‎есть ‎возможность ‎устранить ‎такую‏ ‎возможность.‏ ‎Это ‎флаг‏ ‎IgnoreUnrelatedDimensions в ‎настройках‏ ‎группы ‎мер:

По ‎умолчанию ‎он ‎разрешает‏ ‎пользователю‏ ‎связывать‏ ‎в ‎MDX-запросе‏ ‎что ‎угодно‏ ‎с ‎чем‏ ‎угодно.

Полезно‏ ‎сбросить ‎этот‏ ‎флаг ‎для ‎устранения ‎возможности ‎случайно‏ ‎или ‎в‏ ‎результате‏ ‎ошибки ‎получить ‎некорректные‏ ‎данные ‎в‏ ‎отчётах:

Теперь ‎при ‎попытке ‎соединить‏ ‎несоединяемое‏ ‎сервер ‎просто‏ ‎не ‎будет‏ ‎выдавать ‎какие-либо ‎данные ‎на ‎несуществующих‏ ‎пересечениях.‏ ‎Никакой ‎ошибки‏ ‎или ‎предупреждения‏ ‎при ‎этом ‎по-прежнему ‎не ‎генериуется,‏ ‎но‏ ‎такое‏ ‎поведение ‎всё‏ ‎равно ‎лучше.‏ ‎Теперь ‎пользователь‏ ‎быстрее‏ ‎обнаружит ‎ошибку,‏ ‎поймёт ‎её ‎причину ‎и ‎не‏ ‎увидит ‎в‏ ‎отчёте‏ ‎некорректные ‎результаты.

Ещё ‎удобнее‏ ‎стало ‎в‏ ‎Экселе. ‎Я ‎пытаюсь ‎некорректно‏ ‎разложить‏ ‎меры ‎по‏ ‎строкам, ‎но‏ ‎даже ‎сами ‎значения ‎атрибутов ‎в‏ ‎сводной‏ ‎таблице ‎не‏ ‎показываются:

Однако, ‎если‏ ‎вдруг ‎потребуется ‎вернуться ‎к ‎поведению‏ ‎по‏ ‎умолчанию,‏ ‎взводить ‎флаг‏ ‎IgnoreUnrelatedDimensions и ‎пересчитывать‏ ‎куб ‎не‏ ‎потребуется.‏ ‎Имеется ‎функцияValidMeasure, которая‏ ‎имитирует ‎эту ‎настройку ‎и ‎схлопывает‏ ‎несвязанные ‎меры‏ ‎по‏ ‎верхнему ‎уровню ‎иерархии:


Читать: 2+ мин
logo Фёдор Самородов

Используйте функции Excel и VBA в MDX-запросах

Существует ‎механизм,‏ ‎позволяющий ‎из ‎MDX-запроса ‎обращаться ‎к‏ ‎внешним ‎функциям.‏ ‎Обычно‏ ‎для ‎этого ‎сначала‏ ‎требуется ‎подключить‏ ‎внешнюю ‎библиотеку ‎с ‎определением‏ ‎функции.‏ ‎Но ‎две‏ ‎таких ‎библиотеки‏ ‎уже ‎подключены ‎по-умолчанию.

А ‎вы ‎знаете,‏ ‎что‏ ‎из ‎MDX-запроса‏ ‎можно ‎вызывать‏ ‎экселевские ‎(и ‎ВБА) ‎функции? ‎Да,‏ ‎это‏ ‎то‏ ‎самое ‎чувство,‏ ‎когда ‎вы‏ ‎легко ‎можете‏ ‎добиться‏ ‎желаемого ‎результата‏ ‎в ‎Экселе, ‎а ‎вот ‎в‏ ‎MDX…

Попробуйте ‎обратиться‏ ‎к‏ ‎внешним ‎функциям ‎через‏ ‎префикс ‎Excel! или‏ ‎VBA!. Вот ‎так:

Студия ‎подчёркивает ‎вызов‏ ‎функции‏ ‎Format красным ‎—‏ ‎это ‎ошибка?‏ ‎Ведь ‎такой ‎функции ‎нет ‎в‏ ‎языке‏ ‎MDX! ‎Верно,‏ ‎нет. ‎Но‏ ‎зато ‎она ‎есть ‎в ‎VBA.

Обращаться‏ ‎к‏ ‎функциям‏ ‎VBA ‎можно‏ ‎либо ‎через‏ ‎приставку ‎«VBA!», либо‏ ‎через‏ ‎«VBAMDX.», а ‎можно‏ ‎и ‎вообще ‎без ‎префикса:

А ‎ещё‏ ‎вы ‎можете‏ ‎аналогичным‏ ‎образом ‎задействовать ‎функции‏ ‎Excel. ‎Вот‏ ‎так:

Однако, ‎прежде ‎чем ‎использовать‏ ‎такой‏ ‎«ход ‎конём»,‏ ‎примите ‎во‏ ‎внимание ‎три ‎вещи.

Во-первых, ‎вам ‎доступны‏ ‎не‏ ‎все ‎функции,‏ ‎а ‎только‏ ‎те, ‎использование ‎которых ‎в ‎контексте‏ ‎MDX-запроса‏ ‎не‏ ‎противоречит ‎здравому‏ ‎смыслу. ‎Из‏ ‎всего ‎богатства‏ ‎ВБА‏ ‎можете ‎использовать‏ ‎вот ‎эти ‎девяносто ‎функций:

Во-вторых, ‎учтите,‏ ‎что ‎если‏ ‎вам‏ ‎понадобятся ‎функции ‎из‏ ‎Экселя, ‎то‏ ‎вам ‎придётся ‎установить ‎сам‏ ‎эксель‏ ‎на ‎машину‏ ‎с ‎аналитическим‏ ‎сервером ‎(следите ‎за ‎совпадением ‎битности).‏ ‎И,‏ ‎кстати, ‎экселевские‏ ‎функции ‎также‏ ‎доступны ‎далеко ‎не ‎все.

И ‎в-третьих,‏ ‎не‏ ‎ждите‏ ‎от ‎этого‏ ‎механизма ‎высокой‏ ‎производительности. ‎Если‏ ‎требуется‏ ‎высокомасштабируемое ‎решение,‏ ‎то ‎применять ‎функции ‎VBA ‎и‏ ‎Excel ‎следует‏ ‎с‏ ‎осторожностью.

Читать: 2+ мин
logo Фёдор Самородов

Как написать динамический MDX-запрос

Есть ‎два‏ ‎популярных ‎сценария ‎использования ‎динамических ‎MDX-запросов:‏ ‎сложная ‎параметризация‏ ‎и‏ ‎контекстно-зависимые ‎запросы. ‎Да,‏ ‎бывает, ‎что‏ ‎без ‎динамических ‎MDX-запросов ‎не‏ ‎обойтись.‏ ‎На ‎этот‏ ‎случай ‎имеются‏ ‎четыре ‎инструмента ‎— ‎они ‎предназначены‏ ‎как‏ ‎раз ‎для‏ ‎конструирования ‎запросов‏ ‎«на ‎лету».

Все ‎умеют ‎писать ‎динамические‏ ‎SQL-запросы.‏ ‎Составляем‏ ‎строку ‎и‏ ‎передаём ‎её‏ ‎команде ‎EXECUTE или‏ ‎процедуре‏ ‎sp_ExecuteSQL:

Многие ‎также‏ ‎в ‎курсе, ‎чем ‎эти ‎два‏ ‎способа ‎различаются.‏ ‎А‏ ‎что ‎насчёт ‎динамических‏ ‎MDX-запросов?

Ведь ‎в‏ ‎языке ‎MDX ‎синтаксические ‎ограничения‏ ‎заметно‏ ‎более ‎суровы,‏ ‎чем ‎в‏ ‎SQL, ‎и ‎без ‎динамического ‎формирования‏ ‎MDX-выражений‏ ‎бывает ‎тяжело.

Для‏ ‎работы ‎с‏ ‎динамическими ‎запросами ‎в ‎MDX ‎имеется‏ ‎набор‏ ‎функций,‏ ‎названия ‎которых‏ ‎начинаются ‎с‏ ‎«StrTo»:

  • StrToMember
  • StrToSet
  • StrToTuple
  • StrToValue

В ‎отличие‏ ‎от‏ ‎языка ‎SQL,‏ ‎при ‎работе ‎с ‎многомерными ‎базами‏ ‎данных ‎мы‏ ‎строим‏ ‎динамически ‎не ‎весь‏ ‎запрос ‎целиком,‏ ‎а ‎отдельные ‎его ‎части:‏ ‎член‏ ‎размерности, ‎перечисление,‏ ‎кортеж ‎или‏ ‎скалярное ‎значение.

Для ‎использования ‎динамической ‎адресации‏ ‎члена‏ ‎размерности ‎используйте‏ ‎функцию ‎StrToMember:

Синтаксически‏ ‎корректное ‎перечисление ‎можно ‎сконструировать ‎функцией‏ ‎StrToSet:

StrToTuple поможет‏ ‎собрать‏ ‎кортеж ‎из‏ ‎координат ‎или‏ ‎из ‎их‏ ‎частей:

А‏ ‎StrToValue позволяет ‎интерпретировать‏ ‎выражение ‎как ‎ячейку:

Подобные ‎динамические ‎конструкции‏ ‎могут ‎пригодиться‏ ‎вам‏ ‎при ‎параметризации ‎MDX-запросов‏ ‎или ‎при‏ ‎индивидуальной ‎нарезке ‎куба ‎с‏ ‎привязкой‏ ‎к ‎текущему‏ ‎пользователю.

Подарить подписку

Будет создан код, который позволит адресату получить бесплатный для него доступ на определённый уровень подписки.

Оплата за этого пользователя будет списываться с вашей карты вплоть до отмены подписки. Код может быть показан на экране или отправлен по почте вместе с инструкцией.

Будет создан код, который позволит адресату получить сумму на баланс.

Разово будет списана указанная сумма и зачислена на баланс пользователя, воспользовавшегося данным промокодом.

Добавить карту
0/2048