Фасад магазина с декоративными светильниками и велосипедом на улице.

Создание решения для сопоставления данных о магазинах в Power BI.

Решения типа «один к одному» (L4L) необходимы для сравнения элементов. Рассмотрим решение, построенное на основе семантической модели.

Делиться

dcc44d680e07b93e13ab4c1f7d1b974c
Фотография Тема Риша на Unsplash.

Что такое принцип «один к одному» (L4L)?

L4L — это механизм, обеспечивающий сравнение только сопоставимых элементов.

Элементами могут быть товары, магазины, группы клиентов и т. д.

Здесь вы можете прочитать подробное объяснение этой темы.

В данном случае я разработаю решение для магазинов.

Магазины могут открываться, закрываться или даже временно приостанавливаться для проведения ремонта, реконструкции или по другим причинам.

Таким образом, магазины могут быть сопоставимы или несопоставимы при сравнении текущих результатов с результатами предыдущего года. Это означает, что если магазин не работал в течение определенного периода в предыдущем году, он несопоставим в текущем году, если он работал в течение того же периода.

L4L обеспечит пользователю отчета возможность выбора, включать или исключать из него магазины, не подлежащие сравнению.

Для выбора состояния L4L я создаю таблицу DIM_L4L:

41f4df5378f31630dc63edf21c04a565
Рисунок 1 – Содержание таблицы DIML4L (Рисунок выполнен автором)

Я могу использовать столбцы L4L_Test и Reason в качестве иерархии в срезе или в матричной визуализации.

Магазины

Я выбрал несколько магазинов из набора данных ContosoRetailDW (подробная информация о наборе данных ContosoRetailDW приведена в разделе «Ссылки» ниже).

В данном случае я выбрал магазины в Италии.

Вот список итальянских магазинов с датами открытия и закрытия, а также указанием регионов L4L:

5570d66457b1e98b2345b73fef22b5d7
Рисунок 2 – Список итальянских магазинов с датами открытия и закрытия, а также названиями штатов (L4L) (Рисунок автором).

В эту таблицу я добавил два столбца с датами открытия и закрытия каждого магазина в конце месяца.

В этой таблице представлены все магазины, которые не поддаются сравнению.

Как видите, магазины 224 и 226 должны были открыться в 2024 году, магазин 222 — закрыться в 2024 году, а магазины 222 и 225 были временно закрыты в 2023 и 2024 годах.

Во время подготовки данных для решения все остальные магазины будут настроены на сопоставимый режим (L4LKey = 1).

На что обратить внимание

Итак, каковы требования?

  1. Мы всегда оглядываемся на прошедший год. В 2025 году мы смотрим на 2024 год, а в 2024 году — на 2023 год.
  2. Пользователь должен иметь возможность выбрать каждый из штатов L4L. Если ни один штат не выбран, данные не фильтруются, и отображаются все магазины.
  3. Мы хотим контролировать результаты по месяцам. Нет необходимости менять ежедневные результаты.
  4. Если в предыдущем году магазин изменил свой статус с 1 (Сопоставимый) на другой, данные необходимо отфильтровать в текущем году.
    Например, магазин открывается в августе 2024 года. Если мы рассмотрим только сопоставимые данные за 2025 год, то не должны увидеть никаких результатов за период с января по июль 2025 года.
  5. Показатели, используемые в отчетах, не следует изменять для достижения необходимых результатов.

Подготовка данных

Во-первых, мне нужно создать таблицу, содержащую все месяцы. Кроме того, она должна включать первую и последнюю даты каждого месяца как в текущем, так и в предыдущем году.

Для этого я создаю таблицу в Power Query, используя в качестве ссылки таблицу Date.

Я оставляю только следующие столбцы и удаляю все остальные:

  • Ключ месяца
  • MonthKeyPY
  • Первый день месяца
  • Последний день месяца
  • Первый день месяца
  • Последний день месяца

После этого я удаляю все дубликаты.

Таблица L4L_Months выглядит следующим образом:

8d20c6dc651cf5210385000d980618b9
Рисунок 3 – Фрагмент таблицы L4L_Months (Рисунок автора)

Далее я создал решение в Power Query, объединив таблицы Store, L4L_Months и таблицу с магазинами и датами открытия и закрытия (название таблицы: L4L_Dates).

Создание решения Power Query

Я создал таблицу, на которую ссылается таблица «Store», и переименовал ее в «Bridge_L4L».

Я удаляю все столбцы, кроме столбца StoreKey.

Далее мне нужна отдельная строка для каждого магазина и каждого месяца.

Для этого я добавляю столбец в таблицу L4L_Months:

3e4f81b7e2232a90faccdc4cd14edc80
Рисунок 4 – Добавление таблицы L4L_Month в новую таблицу Bridge_L4L. (Рисунок автора)

Если развернуть все столбцы таблицы L4L_Month, я получу таблицу, содержащую одну строку для каждой комбинации магазина и месяца:

c8a6b7510d0d6b7bef3de74e51366cda
Рисунок 5 – Таблица Bridge_L4L после расширения таблицы L4L_Months. Теперь каждая строка из таблицы Store умножается на каждый месяц из таблицы L4L_Months (Рисунок автора).

Теперь каждый магазин встречается в списке несколько раз. Чтобы для каждого магазина было уникальное значение «ключ-значение», я добавляю столбец StoreMonthKey:

aaa7df236c269ccafcb5582eaab13a7a
Рисунок 6 – Добавьте StoreMonthKey в таблицу Bridge_L4L для уникальной идентификации каждой строки в теге (Рисунок автора).

Далее я подготавливаю таблицу с данными о магазине под названием «L4L_Dates».

Что касается таблицы Bridge_L4L, я добавил таблицу L4L_Months к таблице stores, которая содержит даты открытия и закрытия (см. рисунок 2).

И снова, как и прежде, я разворачиваю все столбцы из таблицы L4L_Months.

Опять же, каждый магазин встречается в списке несколько раз. Я добавляю один и тот же уникальный ключ-значение для каждого магазина (StoreMonthKey):

 Text.From([StoreKey]) & "_" & Text.From([MonthKey])

На данный момент у меня есть вся необходимая информация для выбора строк с правильным состоянием L4L.

Я должен сделать это в соответствии с датами открытия и закрытия и сравнить их со столбцами First-DateOfMonthPY, используя необходимую логику для каждого состояния L4L.

Для этого я добавляю пользовательский столбец со следующим выражением:

 if [L4LKey] = 2 and       [OpenDate] >= [FirstDayOfMonthPY]   then true      else if [L4LKey] = 3 and          [CloseDate] <= [LastDayOfMonthPY]          then true              else if [L4LKey] = 4 and ([OpenDate] >= [FirstDayOfMonthPY] and [CloseDate] <= [LastDayOfMonthPY])              then true          else false

Я называю этот столбец «Valid», поскольку он отмечает правильные строки для каждого состояния L4L.

Далее я фильтрую данные, чтобы оставить только допустимые строки:

76c68631f5ee3bba2a2bdc5b676f4d1d
Рисунок 7 – Отфильтруйте только допустимые строки, где даты открытия и закрытия находятся в правильном соотношении с First-DayOnMonthsPY и LastDayOnMonthsPY (Рисунок автора).

Следующий шаг — объединение таблицы Bridge_L4L с таблицей L4L_Dates с использованием ранее созданных столбцов StoreMonthKey:

7a4f6ebcc93b4f354cf8d4307fa0aeb3
Рисунок 8 – Объединение двух таблиц Dates_L4L в таблицу Birdge_L4L (Рисунок автора)

На данном этапе мне нужен только столбец L4LKey из таблицы L4L_Dates в таблице Bridge_L4L:

f7bb773682de1de0a419ed614767c0f6
Рисунок 9 – Разверните столбец L4LKex в таблицу Bridge_L4L (Рисунок автора)

В большинстве строк столбец L4LKey содержит значение NULL.

Все эти строки относятся к магазинам и месяцам, которые являются сопоставимыми.

По этой причине я заменяю все нулевые значения на 1:

5605a300942b119fddc3e6643b5c7d77
Рисунок 10 – Замена всех строк в столбце L4LKey, содержащих значение NULL, на значение 1 (Рисунок автора)

Наконец, я удалил все столбцы, кроме необходимых:

71e1c40f9ec4afb36ef0211d1da627b1
Рисунок 11 – Удаление всех ненужных столбцов из таблицы Bridge_L4L (Рисунок автора)

Выполнив эти шаги, я создал таблицу Bridge_L4L, которая может служить фильтром на основе выбранного состояния L4L.

Что еще осталось сделать в Power BI?

Теперь мне нужно разместить новую таблицу Bridge_L4L между таблицами Store и таблицей фактов «Розничные продажи».

Затем я смогу добавить связь между новой таблицей DIM_L4L и таблицей Bridge_L4L.

Но чтобы добавить связь между таблицей Bridge_L4L и таблицей фактов «Розничные продажи», мне необходимо добавить тот же StoreMonthKey в таблицу «Розничные продажи», чтобы однозначно идентифицировать магазин для каждого месяца.

Я делаю это в SQL-запросе для получения данных фактов:

 SELECT [F].[SaleLineCounter]   AS [Sale Line Counter]        ,CONVERT(date, DATEADD(yyyy, 16, [F].[DateKey]))    AS [DateKey]        ,[F].[channelKey]        ,[F].[StoreKey]        ,CONCAT(CONVERT(nvarchar(25), [F].[StoreKey])                ,'_'                ,CONVERT(nvarchar(25), YEAR(CONVERT(date, DATEADD(yyyy, 16, [F].[DateKey]))))                ,RIGHT('00' + CONVERT(nvarchar(25), MONTH(CONVERT(date, DATEADD(yyyy, 16, [F].[DateKey])))), 2)                )              AS [StoreMonthKey]        ,[F].[ProductKey]        ,[F].[PromotionKey]        ,[F].[CurrencyKey]        ,[F].[UnitCost]        ,[F].[UnitPrice]        ,[F].[SalesQuantity]        ,[F].[ReturnQuantity]        ,[F].[ReturnAmount]        ,[F].[DiscountQuantity]        ,[F].[DiscountAmount]        ,[F].[TotalCost]        ,[F].[SalesAmount]        ,[F].[DateKeyYear]    FROM [dbo].[v_FactSales]   AS [F];

Теперь в таблице фактов отображается следующий столбец:

2d081c6e2f41e0293e04bafd377a7c5e
Рисунок 12 – Столбец StoreMonthKey в таблице фактов (Рисунок автора)

В итоге, модель данных для задействованных таблиц выглядит следующим образом:

70d30d6c0b3a6af9c1beca850cffa762
Рисунок 13 – Это модель данных для задействованных таблиц (рисунок автора).

Как видите, у меня только однонаправленные отношения «один ко многим», как и должно быть.

Результаты

После добавления в отчет матричной визуализации с иерархией L4L, магазинами и месяцами в столбцах, я получаю следующий результат для суммы продаж за 2025 год:

0471408c7bd09d54fadce707c99dce70
Рисунок 14 – Результаты сравнения данных, разделенных по состояниям L4L (рисунок автора).

Рассмотрим различные сценарии:

  • Открытие магазинов во Флоренции и Милане:
    Они открылись в мае и октябре 2024 года. Поскольку данные о продажах за эти месяцы отсутствуют, они считаются несопоставимыми. Как видите, данные о продажах переключаются между состояниями «Несопоставимые – Открытие» и «Сопоставимые».
  • Закрытие магазина Contoso Roma:
    Здесь та же картина. Магазин в Риме закрылся в августе 2024 года. Любые результаты после этого месяца будут видны как сопоставимые. Помните, что это демонстрационные данные, и в реальном мире не будет продаж за ноябрь и декабрь. Но при желании вы можете добавить к данным магазина затраты, например, для анализа в отчете о прибылях и убытках.
  • Обновленный магазин Contoso Torino
    Этот магазин был закрыт в период с марта по июль 2024 года. Следовательно, продажи за эти месяцы следует считать несопоставимыми.

Даже если посмотреть на 2024 год, мы видим, что римский магазин правильно обозначен как Refresh, и все остальные магазины, за исключением магазинов во Флоренции и Милане, имеют аналогичную маркировку:

0d3e482972e85cfb85593c3b1aacb334
Рисунок 15 – Вид магазина «Рома» (222) в 2024 году, когда он был временно закрыт в 2023 году (Рисунок автора).

Результаты полностью соответствуют моим ожиданиям.

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

Как это сделать по-другому

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

  • Вы можете перенести эту логику из Power Query в язык программирования по вашему выбору, например, SQL или Python.
  • Этот подход с использованием промежуточной таблицы просто замечательный, поскольку позволяет установить двустороннюю фильтрацию связи между магазином и промежуточной таблицей и скрыть магазины, которые не соответствуют выбранному состоянию L4L. Все таблицы фактов связаны с промежуточной таблицей, что исключает возникновение циклических зависимостей.
  • Более удачным решением может быть интеграция состояния L4L в таблицу(ы) фактов. Это позволит избежать необходимости создания таблицы моста.
  • Вы можете решить добавить логику историзации в логику измерения «Хранилище» и добавить в неё состояние L4L. В этом случае вам необходимо включить иерархию L4L в таблицу «Хранилище». Это может быть наилучшим подходом, поскольку он будет включать стандартную логику SCD2. В то же время это более сложный вариант, поскольку он усложняет подготовку таблицы измерения «Хранилище».

Выбор оптимального подхода к моделированию зависит от ваших требований и имеющихся навыков.

Заключение

Сегодня я показал вам, как создать решение для сопоставления данных по магазинам за разные годы.

Цель создания решения без изменений в показателях DAX достигнута. Всё решение полностью основано на данных.

Это важная тема. Логика, основанная на DAX, может быть нежизнеспособной, поскольку она вводит необходимость включения дополнительной логики DAX в вашу модель данных. Об этом всегда следует помнить при добавлении новых мер.

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

Я большой поклонник решений, основанных на данных. В большинстве случаев они лучше, чем сложный код DAX.

Надеюсь, вы узнали что-то новое и интересное. До скорой встречи!

Ссылки

Здесь представлено видео на YouTube от SQLBI о создании решения L4L для брендов:

Как и в моих предыдущих статьях, я использую пример набора данных Contoso. Вы можете бесплатно скачать набор данных ContosoRetailDW с сайта Microsoft здесь.

Данные Contoso можно свободно использовать в соответствии с лицензией MIT, как описано в этом документе. Я обновил набор данных, чтобы перевести данные в современный формат, и удалил все таблицы, не необходимые для этого примера.

Сальваторе Кальяри Посмотреть все магазины Сальваторе Кальяри

Источник: towardsdatascience.com

✅ Найденные теги: Данных, Магазинах, новости, Решения, Создание, Сопоставления

ОСТАВЬТЕ СВОЙ КОММЕНТАРИЙ

Каталог бесплатных опенсорс-решений, которые можно развернуть локально и забыть о подписках

галерея

Астронавт в кабине шаттла, смотрит в иллюминатор, наушники, солнечный свет.
Телефон с логотипом TikTok на фоне флагов ЕС.
Миниатюрный магнит впервые по силе соперничает с магнитными гигантами.
Бутылка шоколадного напитка Huel на фоне продуктов в холодильнике.
Спиральная галактика на звездном фоне, космическое пространство, астро-фотография.
Антарктический пейзаж с мхами и лишайниками на фоне заснеженных гор и моря.
Минималистичный серебристый док-станция для гаджетов на рабочем столе с техникой.
Шесть режимов перевода и ИИ-ассистент: костные наушники Voitrans
Человек держит смартфон с иконками социальных сетей на экране.
Image Not Found
Бутылка шоколадного напитка Huel на фоне продуктов в холодильнике.

Huel пытается решить проблему «бремени» еды.

Технически это еда. (Но на вкус это не еда.) Виктория Сонг, старший рецензент в области носимых технологий. Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной странице вашего…

Мар 16, 2026
Минималистичный серебристый док-станция для гаджетов на рабочем столе с техникой.

Один адаптер вместо трёх: компактная зарядка TORRAS

Команда TORRAS переосмыслила привычный формат зарядки для Apple Watch и предложила решение под углом 45 градусов, которое позволяет использовать часы как настольные во время зарядки и при этом надёжно фиксирует их благодаря усиленному магниту.  Новый аксессуар объединяет…

Мар 16, 2026
Шесть режимов перевода и ИИ-ассистент: костные наушники Voitrans

Шесть режимов перевода и ИИ-ассистент: костные наушники Voitrans

На рынке появились первые ИИ-наушники с костной проводимостью и функцией перевода в реальном времени.  Разработчики из компании Voitrans объединили передовые технологии искусственного интеллекта с комфортом открытого формата: звук передаётся через кости черепа, оставляя уши свободными, что особенно…

Мар 16, 2026
Человек держит смартфон с иконками социальных сетей на экране.

Участник Сколково запускает тестирование решений для контроля смартфонов в школах

© Freepic Компания «Велтер», резидент Сколково (Группа ВЭБ.РФ), приступила к реализации пилотного проекта по тестированию решений Velter в общеобразовательных учреждениях. Инициатива стартует в Тюменской области на базе ЧОУ «Еврогимназия» и направлена на формирование у участников образовательного процесса…

Мар 16, 2026

Впишите свой почтовый адрес и мы будем присылать вам на почту самые свежие новости в числе самых первых