ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

前端精读周刊 · LOD 表达式 15 大业务场景实战(下):复购阵列、相对周期过滤与客户年度购买频率

前端精读周刊 · LOD 表达式 15 大业务场景实战(下):复购阵列、相对周期过滤与客户年度购买频率 文档技术博客教程【免费下载链接】weekly前端精读周刊。帮你理解最前沿、实用的技术。项目地址https://gitcode.com/GitHub_Trending/we/weekly点击查看免费下载本篇承接 精读《15 大 LOD 表达式 - 上》继续拆解 Tableau 官方 Top 15 LOD Expressions 案例中的第 915 个场景覆盖 时间段内最后一天取值、复购阵列、区间均值差异、相对周期过滤、用户活跃频率、品类贡献占比、客户群年度购买频率 七类高频分析需求。读完你可以掌握 INCLUDE、FIXED、EXCLUDE 在真实业务中的选型逻辑以及如何把复杂需求拆解成中间计算字段 最终聚合表达式的标准套路。前置知识回顾LOD 的三板斧在进入场景之前先回顾 精读《什么是 LOD 表达式》 中的核心结论LOD 的全称是 Level Of Detail详细级别它允许在一个查询中描述不同的数据粒度最终产出会被贴合回当前视图的详细级别中参与计算。三种表达式的定位是{ fixed [维度] : 聚合 }完全脱离视图按指定维度固定计算{ include [维度] : 聚合 }在视图粒度之上额外追加维度计算{ exclude [维度] : 聚合 }在视图粒度之上移除维度计算。同时要记住一条铁律表达式计算必须限定在同样的详细粒度下聚合表达式如max(Date)无法直接出现在明细级别的行中——这正是本篇第 9 个场景的切入点。9. 某时间段内最后一天的值INCLUDE 如何下推到明细行需求要实现股票平均每日收盘价 vs 当月最后一天收盘价的对比趋势图难点在于对比的并非某段时间而是当月最后一天的收盘价这个值必须借助 LOD 才能拿到。设想原表如下DateTickerAdj Close29/08/2013SYMC$128/08/2013SYMC$227/08/2013SYMC$3按月聚合作为横轴、avg([Adj Close])作为纵轴可以得到均值但要计算最后一天收盘价对比需要先构造一个Max Date字段。为什么普通max(Date)不行如果直接使用max(Date)聚合在月粒度聚合后确实能看到 Max DateMonth of DateTickerAvg, Adj CloseMax, Date08/2013SYMC$229/08/2013但问题在于max(Date)是聚合表达式只能在 group by 聚合的查询下生效。而我们要构造最后一天收盘价这个字段表达式是[Close value on last day] IF [Max Date] [Date] THEN [Adj Close] ELSE 0 END这个表达式计算的明细级别是天粒度在天粒度下max(Date)根本算不出来每行的Max, Date都是空DateTickerAdj CloseMax, Date29/08/2013SYMC$128/08/2013SYMC$227/08/2013SYMC$3这正是聚合表达式不能在非聚合的明细级别中出现的典型场景。INCLUDE 解法用{ include : max([Date]) }即可解决。注意这里INCLUDE 没有给任何维度参数意味着永远以当前视图的明细级别计算因此这个字段被下推到明细表做计算时可以出现在每一行DateTickerAdj Close{ include : max([Date]) }29/08/2013SYMC$129/08/201328/08/2013SYMC$229/08/201327/08/2013SYMC$329/08/2013随后按原思路组装[Close value on last day]再对对比值做sum([Close value on last day])聚合即可。拓展横轴按年聚合如果把横轴从月改为年{ include : max([Date]) }会以年这个粒度计算max([Date])得到的是每年的最后一天然后下推到明细表——整整一年 365 行数据里[Close value on last day]只有最后一天那行是真实收盘价其余行都是 0DateTickerAdj Close[Close value on last day]31/12/2013SYMC$1$130/12/2013SYMC$2$1............03/01/2013SYMC$7$102/01/2013SYMC$8$101/01/2013SYMC$9$1原理提示从 精读《什么是 LOD 表达式》 的论述可知LOD 字段的本质是两个不同 group by 规则的查询结果做 join 后再贴合回当前粒度。这里的{ include : max([Date]) }内部以视图粒度 group by 求 max外部再以一对多关系合并回明细行所以每一行都能带上所属月份的 Max Date。10. 复购阵列两次购买时间的求法需求希望查看客户第一次购买到第二次购买间隔季度的复购阵列图关键在于求出第一次与第二次购买的季度时间差。第一步首次购买时间每位客户的首单时间可以直接用 FIXED 固定客户 ID 后取min[1st purchase] { fixed [customer id] : min([order date]) }第二步第二次购买时间的小技巧第二次购买时间不能直接min否则会取到首单本身。这里的技巧是先构造一个排除首单的列让首单那一行变成 null[repeat purchase] iif([order date] [1st purchase], [order date], null)利用min函数计算时忽略 null 的特性得到第二次购买时间[2nd purchase] { fixed [customer id] : min([repeat purchase]) }第三步季度间隔最后用datediff计算两次购买之间的季度数[quarters repeat to purchase] datediff(quarter, [1st purchase], [2nd purchase])该场景提示了一个可复用的通用手法当要排除某一特定记录取下一个极值时用 IF/IIF 把目标记录置为 null再借助聚合函数天然忽略 null 的行为比排序取第二名之类的做法简洁得多。11. 范围平均值差异百分比FIXED 计算参考区间均值需求希望把趋势图的每个点与图中选定区域两个虚线范围内的区间的均值做差异百分比并生成一条新的折线图放在上方。重点是上面折线图 y 轴字段的构造。第一步截取参考区间的收盘值[Close value in reference period] IF [Date] [Start reference date] AND [Date] [End reference date] THEN [Adj close] END这段表达式只在日期位于指定区间内时返回[Adj close]区间之外返回 null相当于只保留了参考区间的数据。第二步FIXED 计算区间均值参考区间的均值与视图当前粒度无关只与 Ticker 相关用 FIXED 固定[Average daily close value between ref date] { fixed [Ticker] : AVG([Close value in reference period]) }第三步差异百分比[percent different from ref period] ([Adj close] - [Average daily close value between ref date]) / [Average daily close value between ref date]最后直接用[percent different from ref period]绘制上方的折线图即可。这个场景与 上篇第 4 个场景占总体百分比 一脉相承跨详细级别的参考值计算一律优先考虑 FIXED——因为参考区间的均值不依赖视图维度是确定性的固定粒度。12. 相对周期过滤用年内第几天做同比卡点需求对比两个周期数据差异时容易踩到数据不全的坑比如今年 3 月的数据只产出到 6 号却拿去和去年 3 月整月数据对比显然不合理。相对周期过滤就是为了解决这类同比基准不一致的问题。思路不能直接用日期对比不能直接用日期过滤因为今年数据天然比去年小日期上今年总是晚于去年。正确做法是找到今年最新数据的日期把去年同一天之后的数据全部过滤掉。第一步找到最新数据日期利用不带条件的 FIXED 表达式等价于{ fixed : ... }即全表固定粒度[max date] { max([date]) }第二步换算成年内第几天用datepart把日期换算成它在一年中的序号作为统一标尺[day of year of max date] datepart(dayofyear, [max date])[day of year of order date] datepart(dayofyear, [order date])[day of year of max date]就是一个卡点——任何超过今年这么多天的数据都要被过滤掉。第三步构造过滤条件[period filter] [day of year of order date] [day of year of max date]把[period filter]字段作为筛选条件过滤为 true即可完成同比周期的对齐。该方案的精髓在于把日期区间对比转换为年内序号对比规避了跨年份日期比较的语义混乱而datepart(dayofyear, ...)是这套打法的核心转换函数。13. 用户登陆频率活跃月数 ÷ 登陆次数需求绘制每个用户每月登陆频率分布图。指标的算法是用户总活跃时间 ÷ 总登陆次数。第一步计算总活跃月数用 FIXED 固定用户 ID分别取最早、最晚登陆时间[first login] { fixed [user id] : min([log in date]) }[last login] { fixed [user id] : max([log in date]) }计算两者的月份差即为活跃月数[total months user is active] datediff(month, [first login], [last login])第二步计算总登陆次数同样固定用户 ID对登陆日期计数[numbers of logins per user] { fixed [user id] : count([login date]) }第三步两者相除得到频率[login frequency] [total months user is active] / [numbers of logins per user]出图把[login frequency]移到横轴纵轴用 count distinct 用户 ID 即可。这个例子是FIXED 计算结果 普通字段二次运算的标准组合两个 FIXED 字段都保持与视图粒度一致因此可以直接相除参与计算符合 LOD 表达式最终贴合当前详细级别的特性。14. 比例笔刷跨详细级别的占比计算这是 LOD 最常见的场景求各品类销量占该品类总销量的贡献占比。例如当前详细级别是 category country品类 国家要算某个国家某品类的销量占该品类在所有国家累计销量的比例。直接用一个 FIXED 表达式即可sum(sales) / sum({ fixed [category] : sum(sales) })解析分母固定品类得到各品类在所有国家的累积销量这个值被贴合回 category country 粒度的每一行分子是当前粒度下的销量两者在相同详细级别下相除就是贡献占比。与 上篇占总体百分比 中的sum([sales]) / max({ sum([sales]) })相比本例直接对 LOD 字段套sum聚合由于 LOD 字段在每行的值相同sum等价于行数 × 该值用于占比分母时结果正确。如果视图粒度变细比如再加一个维度分母会随行数放大此时改用max({ fixed [category] : sum(sales) })更稳妥——这也是官方例子里用max包裹 LOD 字段的原因总销量只有一条数据用 max/min/sum 结果都一样。15. 按客户群划分的年度购买频率累计占比与 WINDOW_SUM需求如何证明老客户忠诚度更高把客户按注册首购年份划分成 Cohort 群组作为图例观察每个群组每年至少购买 N 次的客户占比分布。由于看的是至少购买 N 次累计口径各条线的对比才有说服力——如果看恰好购买 N 次老客户可能购买 1 次的人少、购买 10 次的人多难以直接对比。第一步生成图例字段客户群按最早购买年份划分顾客群[Cohort] { fixed [customer id] : min(Year([order date])) }第二步统计每个购买次数下的客户数与第 1 个例子类似地按订单数统计客户数区别在于不仅按客户 ID group还要进一步对最早购买日期Cohort做拆分{ fixed [customer id], [Cohort] : count([order id]) }第三步把恰好购买 N 次转成至少购买 N 次上面的字段作为 X 轴后Y 轴用count(customer id)只能得到恰好购买 N 次的客户数。要得到至少购买 N 次需要从当前次数累加到最后一次也就是 DESC 方向的窗口求和[Running Total] WINDOW_SUM(count(customer id), 0, LAST())WINDOW_SUM(expr, 0, LAST())表示从当前分区起点累加到分区末尾即至少购买 N 次 购买 N 次 购买 N1 次 ... 购买 MAX 次。第四步转换为占比实际 Y 轴计算的是占比因此用至少购买 N 次除以各 Cohort 下的总购买次数[Running Total] / sum({ fixed [Cohort] : count([customer id]) })将结果字段拖入图表按 Cohort 着色即可得到各客户群的累计购买频率曲线。这个场景综合了 FIXED构造 Cohort、统计各群总数与窗口函数WINDOW_SUM 累计是整篇中最复合的一个案例先用 LOD 把数据切成 Cohort 群组再在表计算层做累计占比体现了LOD 字段只负责跨粒度取数、窗口函数负责行内累计的分工。总结难点不在语法而在需求拆解纵观第 915 个场景所有表达式都是基于 fixed、include、exclude 三个基础用法的组合叠加。真正的难点并不在于 LOD 表达式的语法而在于精确理解需求先把业务诉求翻译成按什么粒度、求什么值拆解计算步骤把复杂指标拆成一个个可独立验证的中间字段如本篇的[1st purchase]、[max date]、[Cohort]在正确的步骤使用 LOD判断每一步是否需要跨详细级别计算以及该用 FIXED 还是 INCLUDE/EXCLUDE。结合 上篇的使用心法 与本篇场景可以沉淀出一张选型速查表场景特征推荐用法本篇示例计算与视图粒度无关、需按固定维度聚合FIXED场景 10/11/13/14 的区间均值、首末登录时间、品类汇总需在当前视图粒度上追加更低维度计算INCLUDE场景 9 的当月最后一天下推明细需移除某维度但保留视图其余维度EXCLUDE上篇场景 6 的选中分类对比需要行内累计 / 跨行聚合后再运算LOD 窗口函数场景 15 的 WINDOW_SUM 累计占比最后回到原理层面LOD 表达式之所以看起来神奇、似乎能和数据贴合得天衣无缝是因为LOD 背后就是表之间的 join而不同详细级别就表示不同的 group by 规则。理解了这一层再回头看{ include : max([Date]) }能出现在每一行明细、{ fixed [customer id] : min([order date]) }能轻松取到每客户首单一切就都顺理成章了。本系列三篇LOD 表达式原理 → 场景 18 → 场景 915共同构成了 Tableau LOD 的完整实战图谱可作为日常数据分析取数的速查手册。赞分享文档技术博客教程【免费下载链接】weekly前端精读周刊。帮你理解最前沿、实用的技术。项目地址https://gitcode.com/GitHub_Trending/we/weekly点击查看免费下载相关推荐前端精读周刊15 大 LOD 表达式实战精读上——八大业务场景中的 FIXED、INCLUDE 与 EXCLUDE前端精读周刊15 大 LOD 表达式实战精读上——八大业务场景中的 FIXED、INCLUDE 与 EXCLUDE LODLevel Of Detail文档技术博客教程BurpSuiteHTTPSmuggler开发者指南源码解析与扩展开发教程BurpSuiteHTTPSmuggler开发者指南源码解析与扩展开发教程 BurpSuiteHTTPSmuggler是一款强大的Burp Suite扩展工具springdoc-openapi高级定制自定义API信息与安全配置详解springdoc openapi高级定制自定义API信息与安全配置详解 在现代API开发中清晰的文档和完善的安全配置是保障服务可用性与安全性的关键。 sp后端API设计文档上一篇KnowStreaming 前端多集群管理应用 layout-clusters-fe 开发与构建指南下一篇KoboldCpp UI 高层架构解析Svelte 前端的状态流、服务层与 MCP 集成创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表