169_技巧_Power BI 依据促销日历计算销售金额

news2024/9/20 18:47:10

169_技巧_Power BI 依据促销日历计算销售金额

一、背景

在各位表格表姐们计算销售金额的时候,有一个绕不开的问题:商品有促销的问题,需要使用对应的促销价来计算销售额。

按照惯例还是先来看看结果

169-1

Power BI 公共 web 效果:https://demo.jiaopengzi.com/pbi/169-full.html

二、场景解析

上图中结果其实非常简单,用一个矩阵就表示了结果。从DAX 建模和数据清洗还是有一定的要求。

数据采集需要符合业务需求和采集便利性。业务人员或者说我们数据的管理人员,更希望数据是在一行里面尽可能简短的表达完整我们的信息(拉链表)。但是在我们使用 DAX 做模型的时候,更希望看到的是流水表,这两点就是矛盾的。

接下来我们就使用 Power Query 来解决这个问题。

1、促销日历 & 价格表

案例中,价格表、促销日历都是使用拉链表的形式来记录信息。这不利于我们建模分析,于是需要使用 Power Query 来处理一下数据。

注意:促销日期展开拉链 ,这两个步骤,从拉链表展开到流水表。

let
    源 = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMjIwMtY31jdU0oExLYDMp73Tn/bsAjKezdj3fMmupzNXANkGepamSrE6UD1GCD1ApgmQ/WTHHIimFw2bn83ZBdZhYaEUGwsA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [促销开始日期 = _t, 促销结束日期 = _t, 区域 = _t, 产品 = _t, 折扣 = _t]),
    更改的类型 = Table.TransformColumnTypes(源,{{"促销开始日期", type date}, {"促销结束日期", type date}, {"折扣", type number}}),
    促销日期 = Table.AddColumn(更改的类型, "促销日期", each List.Dates([促销开始日期], Number.From([促销结束日期]-[促销开始日期])+1, #duration(1,0,0,0))),
    展开拉链 = Table.ExpandListColumn(促销日期, "促销日期"),
    类型 = Table.TransformColumnTypes(展开拉链,{{"促销日期", type date}}),
    删除的列 = Table.RemoveColumns(类型,{"促销开始日期", "促销结束日期"})
in
    删除的列

169-2

注意:日期展开 这两个步骤,从拉链表展开到流水表。

let
    源 = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMjIwMtY31DdU0oEyjfSNQZyXexY8W9AOZBgaGCjF6uBROGXd89kzwKL4Fb5o2Pxszi4gw4yAwmcz9j1fsuvpzBVAtiVCrRFCrRGmM40IKYQ505iAQrgzTQkoRHYmMJCAimMB", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [开始执行日期 = _t, 结束执行日期 = _t, 产品 = _t, 价格 = _t]),
    更改的类型 = Table.TransformColumnTypes(源,{{"开始执行日期", type date}, {"结束执行日期", type date}, {"产品", type text}, {"价格", Int64.Type}}),
    日期 = Table.AddColumn(更改的类型, "执行日期", each List.Dates([开始执行日期], Number.From([结束执行日期]-[开始执行日期])+1, #duration(1,0,0,0))),
    展开 = Table.ExpandListColumn(日期, "执行日期"),
    类型 = Table.TransformColumnTypes(展开,{{"执行日期", type date}}),
    删除的列 = Table.RemoveColumns(类型,{"开始执行日期", "结束执行日期"})
in
    删除的列

169-3

2、常规表格

销售明细按照常规的方式处理字段类型即可,同时准备好我们的日期表,维度表:区域表、产品表等。

169-4

3、表间关系

如下关系为: 多对一

  • ‘销售明细’[产品] --> ‘产品表’[产品]
  • ‘销售明细’[日期] --> ‘日期表’[Dates]
  • ‘销售明细’[区域] --> ‘区域表’[区域]
  • ‘促销日历’[促销日期] --> ‘日期表’[Dates]
  • ‘促销日历’[区域] --> ‘区域表’[区域]
  • ‘产品价格’[执行日期] --> ‘日期表’[Dates]
  • ‘产品价格’[产品] --> ‘产品表’[产品]
  • ‘促销日历’[产品] --> ‘产品表’[产品]

169-5

三、DAX

这里我们使用了两种方式来写度量值。一种是使用 LOOKUPVALUE ,这种写法可以如下关系去掉。

  • ‘促销日历’[促销日期] --> ‘日期表’[Dates]
  • ‘促销日历’[区域] --> ‘区域表’[区域]
  • ‘产品价格’[执行日期] --> ‘日期表’[Dates]
  • ‘产品价格’[产品] --> ‘产品表’[产品]
  • ‘促销日历’[产品] --> ‘产品表’[产品]
销售金额-LOOKUPVALUE = 
VAR saleData =
    CALCULATETABLE ( '销售明细' )
VAR saleDataAdd =
    ADDCOLUMNS (
        saleData,
        "@price", LOOKUPVALUE ( '产品价格'[价格], '产品价格'[产品], '销售明细'[产品], '产品价格'[执行日期], '销售明细'[日期] ),
        "@promotion",
            VAR discount =
                LOOKUPVALUE (
                    '促销日历'[折扣],
                    '促销日历'[产品], '销售明细'[产品],
                    '促销日历'[促销日期], '销售明细'[日期],
                    '促销日历'[区域], '销售明细'[区域]
                )
            RETURN
                IF ( ISBLANK ( discount ), 1, discount )
    )
VAR result =
    SUMX ( saleDataAdd, [@price] * [@promotion] * [销售量] )
RETURN
    result

另外一种使用 RELATEDTABLE ,这种方式充分的利用到了维度表和事实表之间的关系

销售金额-RELATEDTABLE = 
VAR saleData =
    CALCULATETABLE ( '销售明细' )
VAR saleDataAdd =
    ADDCOLUMNS (
        saleData,
        "@price", MAXX ( RELATEDTABLE ( '产品价格' ), '产品价格'[价格] ),
        "@promotion",
            VAR discount =
                MAXX ( RELATEDTABLE ( '促销日历' ), '促销日历'[折扣] )
            RETURN
                IF ( ISBLANK ( discount ), 1, discount )
    )
VAR result =
    SUMX ( saleDataAdd, [@price] * [@promotion] * [销售量] )
RETURN
    result

对比两种写法的效率,明显能看到 销售金额-RELATEDTABLE销售金额-LOOKUPVALUE 更快。同时 DAX 代码量也相对更少。

169-6

四、总结

  1. 在数据收集和规范阶段,可以把数据要求为拉链表的形式,更便于对业务人员对数据的维护,同时也能很好的使用 Power Query 来做数据清洗便于建立分析模型。

  2. 类似促销日历的这种形式,在 dax 建模的时候,我们使用一层一层的迭代的形式往数据上去叠加,同时需要考虑数据最小粒度,这里的价格表和促销日历,我们是使用日期来进行约束描述的。这样能应对不同形式的价格调整,不会对模型造成的影响。

  3. 当前案例对表间关系的理解需要到位,不然容易使用 LOOKUPVALUE ,当然无论什么方式,只要能解决业务问题都是好的方式,只是效率相对低一些。

请关注


全网同名搜索 焦棚子

如果对你有帮助,请 点赞关注三连 支持一下,这是我们更新的动力。

by 焦棚子

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/391748.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用docker进行Mongoyapi安装,Mongo重启yapi重启

在这里我使用Linux虚拟机作为docker服务器,本机通过xshell进行远程操作。 Mongo安装:docker run -d --name mongo-yapi mongo; yapi安装:1)拉取yapi docker pull registry.cn-hangzhou.aliyuncs.com/anoy/yapi 2)初…

2023款欧拉好猫上市,12.98万起

上周,2023款欧拉好猫焕新上市。2023款好猫共推出5个车型: •401km标续航,舒享型/豪华型/尊贵型,分别是12.98/13.98/14.98万元; •501km长续航,豪华型/尊贵型,分别是15.58/16.58万元;…

00后整顿职场,当摸鱼测试员遇上了内卷00后。

在程序员职场上,什么样的人最让人反感呢? 是技术不好的人吗?并不是。技术不好的同事,我们可以帮他。 是技术太强的人吗?也不是。技术很强的同事,可遇不可求,向他学习还来不及呢。 真正让人反感的,是技术平平&…

【PaddleOCR-kie】一、关键信息抽取:使用VI-LayoutXLM模型推理预测(SER+RE)

背景:在训练自己数据集进行kie之前,想跑一下md里面的例程,但md教程内容混乱,而且同一个内容有多个手册,毕竟是多人合作的项目,可能是为了工程解耦,方便更新考虑……需要运行的模型和运行步骤散落…

没有钱怎么创业?一分钱没有如何能创业成功?

限制人创业成功的从来都不是资金,而是能力,这个道理很多人都可能不懂,多数人习惯了庸庸碌碌、日复一日地打工行为,却不知如何创业,那么,没有钱怎么创业?一分钱没有如何能创业成功呢?…

【深度学习】预训练语言模型-BERT

1.BERT简介 BERT是一种预训练语言模型(pre-trained language model, PLM),其全称是Bidirectional Encoder Representations from Transformers。下面从语言模型和预训练开始展开对预训练语言模型BERT的介绍。 1-1 语言模型 语言模型 &#xf…

iOS(一):Swift纯代码模式iOS开发入门教程

Swift纯代码模式iOS开发入门教程项目初始化(修改为纯代码项目)安装第三方库(以SnapKit库为例)桥接OC库(QMUIKit)封装视图并进行导航跳转示例:使用 TangramKit 第三方UI布局库应用国际化添加 R.s…

NICEGUI---ROS开发之中常用的GUI工具

0. 简介 对于ROS来说,如果不具备一定知识的人员来使用这些我们写的算法,如果说没有交互,这会让用户使用困难,所以我们需要使用GUI来完成友善的数据交互,传统的GUI方法一般有PYQT这类GUI方法,但是这类GUI工…

激光炸弹(前缀和)

地图上有 N 个目标,用整数 Xi,Yi 表示目标在地图上的位置,每个目标都有一个价值 Wi。注意:不同目标可能在同一位置。现在有一种新型的激光炸弹,可以摧毁一个包含 RR 个位置的正方形内的所有目标。激光炸弹的投放是通过卫星定位的&…

顺序表以及链表的应用及区别(包含OJ讲解)

前面我已经发过怎么实现链表以及顺序表,今天大概的总结一下。 顺序表: 1.能够随时的存取,比较方便。 2.插入删除时,需要挪动数据,比较麻烦,因为是连续存储。 3.存储密度相对于链表来说是比较高的&#…

C++类的组合

C类的组合什么是类的组合初始化参数列表使用类的组合案例分析组合构造和析构顺序问题this指针基本用法和作用什么是类的组合 类的组合就是以另一个对象为数据成员,这种情况称为类的组合 1.优先使用类的组合,而不是继承 2.组合表达式的含义 一部分关系 初…

用户登录请求100w/每天, JVM如何调优

用户登录请求100w/每天, JVM如何调优 大概可以分为以下8个步骤。 Step1:新系统上线如何规划容量? 1.套路总结 任何新的业务系统在上线以前都需要去估算服务器配置和JVM的内存参数,这个容量与资源规划并不仅仅是系统架构师的随意估算的&am…

springboot启动过程加载数据笔记(springboot3)

SpringApplication AbstractApplicationContext PostProcessorRegistrationDelegate ConfigurationClassPostProcessor ConfigurationClassParser 一堆循环和调用 ComponentScanAnnotationParser扫描 processConfigurationClass.doProcessConfigurationClass(configClass, so…

网络编程(二)

6. TCP 三次握手四次挥手 HTTP 协议是 Hype Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web)服务器(sever)传输超文本到客户端(本地浏览器…

小众但意外觉得蛮好用的剪辑软件!纯良心分享

爱剪辑 有开屏广告,一共3个界面:首页、剪同款、我的。 剪辑、配乐、字幕、滤镜、加速、贴纸、配音等主流功能都有。 特色功能有剪裁视频、倒放视频、视频旋转、视频转换GIF、转场、提取音频、画中画等。 还可以拼接视频,不过不支持FLV等小众文…

人员摔倒识别预警系统 人员跌倒检测算法 yolov7

人员摔倒识别预警系统 人员跌倒检测算法基于yolov7网络模型计算机识别技术,人员摔倒识别预警系统 人员跌倒检测算法对画面中人员摔倒进行实时检测识别抓拍告警。YOLOv7 的策略是使用组卷积来扩展计算块的通道和基数。研究者将对计算层的所有计算块应用相同的组参数和…

buuctf-pwn write-ups (11)

文章目录buu083-x_ctf_b0verfl0wbuu084-picoctf_2018_leak_mebuu085-inndy_echobuu086-hitcontraining_unlinkbuu087-ciscn_2019_final_3buu088-axb_2019_fmt64buu089-wustctf2020_name_your_catbuu090-pwnme1buu091-axb_2019_brop64buu092-[极客大挑战 2019]Not Badbuu083-x_c…

JAVA开发运维(nginx工作原理)

nginx源码目录结构: . ├── auto 自动检测系统环境以及编译相关的脚本 │ ├── cc 关于编译器相关的编译选项的检测脚本 │ ├── lib nginx编译所需要的一些库的检测脚本 │ ├── os 与平台相关的一些系统参数…

2023-03-06 debian11 最小安装记录

1.镜像准备,根据个人需求下载debian 版本Debian -- 获取 Debian2.上传到VSAN 内容库我这边是在vm里面安装的,就直接上传到内容库备用(根据个人需求存放)3.分配虚拟主机配置根据个人需要配置4.开始最小安装1.在界面中选择Install&a…

Packet Tracer--配置帧中继

Packet Tracer--配置帧中继 拓扑图: 设备参数: 设备 接口 DLCI R1 S0/2 102,103 R2 S0/2 201 R3 S0/2 301 R1---R2 Se1:102-----Se2:201 R1---R3 Se1:103-----Se3:301 IP参数 设备 接口 IP地址…