前不久,我们应数据粉需求举办了一场 Tableau 计算主题的线上分享,不仅介绍了基础计算、表计算与详细级别(LOD)表达式的计算逻辑,还通过实操演示,分享如何利用 Tableau 日期函数和参数功能实现同比、环比、YTD、MTD 等时间计算用例。
但实际上,业务分析需求可能非常复杂。就日期计算而言,围绕某一个日期值或时间粒度进行比较的计算就涉及数十种。因此,我们不妨来探索一下由资深用户 Luke Stanke 整理并分享到 Tableau Public 的工作簿——Date Calculations Cheat Sheet。
如果你是 Tableau 用户,希望快速轻松地进行日期计算,那么这份指南一定会让你爱不释手!话不多说,让我们马上开始探索吧~
TIPS:如何使用日期计算速查指南?
在这份日期计算速查指南中,Luke 基于数据集中的“最新日期”,列举了与年、季度、月、周、天等不同级别进行比较的场景和计算示例。你只需输入业务数据源中的日期字段名,并选择所需的日期计算类型,随即工作簿将更新表达式,以便你复制和使用。
如果仅参考计算示例的函数与结构,可依照以下逻辑在业务数据中对日期字段进行比较:
01 创建返回布尔值(True/False)的计算。将日期字段放在等式左侧,将比较值放在等式右侧。比如,返回今天的日期:[Date] = TODAY()
02 基于布尔值获取度量。在 IF 语句中使用上一步创建的布尔值计算,然后在 THEN 语句中指定返回的行级别度量。如有需要,可对计算结果进行聚合。比如,返回今天的某项指标值:SUM( IF [今天的日期] THEN [指标] END )
03 将度量与其他字段进行比较。这一步需确保所有字段都是聚合的。比如,比较某项指标今天与昨天的表现:[今天的指标] - [昨天的指标]。
此外,为了验证示例数据集中计算结果的准确性,工作簿右下角还提供了可观察结果范围的日历热图可视化,以便你确认计算效果是否是想要的。
日期计算示例:年度比较
为了更好进行比较,Luke 将最新日期 [Date | Max] 作为基准字段,{MAX([Date])} 表达式用于返回数据集中最近或最新的日期值。
以示例中的 [Date] 字段为例,数据范围为 2022 年 1 月 1 日至 2024 年 9 月 25 日。因此,从日历热图中可以看到 2024 年 9 月 25 日的标记被高亮显示,这意味着计算结果准确。
Y1:YTD or Current Year 年初至今或当前年份
计算字段 [CY] 表达式:
DATETRUNC('year', [Date]) = DATETRUNC('year', [Date | Max])
对于在当前年份内且最新日期之前的数据,返回 TRUE。当数据集中包含每一天的数据时使用效果最好。如果数据中存在空值或是实时数据,请将 [Date | Max] 替换为 TODAY()。
从日历热图中,数据整体范围是 2022 年 1 月到 2024 年 9 月。此计算的结果显示 2024 年的每个月都被高亮,表明在这一年的日期中,数据集中有相关的记录。如果你手动更改日历热图上方的日期控件,那么热图的高亮标记数量也会随之变化。
Y2:Prior Year 前一年
计算字段 [PY] 表达式:YEAR([Date]) = YEAR([Date | Max]) - 1
根据数据集中的最新日期,返回前一年的日期数据,则为 TRUE。当数据集中包含每一天的数据时使用效果最好。如果数据中存在空值或是实时数据,请将 [Date | Max] 替换为 TODAY()
如果想在最新年份的第一天,返回前一年的日期数据,则表达式如下:DATEPART("year", [Date]) = DATEPART("year", [Date | Max]) -1
在日历热图中,如果日期值为 2024 年 9 月 25 日,则前一年的日期都是被高亮。
Y3:Prior Year to Date 去年年初至某天前
计算字段 [PYTD] 表达式:
(YEAR([Date]) = YEAR([Date | Max]) - 1) AND [Date] <= DATEADD('year', -1, [Date | Max])
如果返回前一年年初至某天前(不包含)的日期数据,则为 TRUE。当你试图比较某些年中的精确日期时,这个示例最有用。
在日历热图中,如果设定的日期值为 2024 年 9 月 23 日,所以在 2023 年 1 月 1 日到 9 月 22 日的数据都是被高亮的。
Y4:Prior Year to Day 去年年初至最新日期
计算字段 [PYTDay] 表达式:
(YEAR([Date]) = YEAR([Date | Max]) - 1) AND DATEPART('dayofyear', [Date]) <= DATEPART('dayofyear', [Date | Max])
如果返回前一年年初至最新日期(包含)的日期数据,为 TRUE。这个示例适用于比较一年中的天数(第几天),在闰年或使用 ISO8601 日期格式时,将返回不同的相对日期。
在日历热图中,如果设定的日期值为 2024 年 9 月 23 日,所以在 2023 年 1 月 1 日到 9 月 23 日的数据都是被高亮的。
日期计算示例:季度比较
Q1:Current Quarter 当前季度
计算字段 [CQ] 表达式:DATETRUNC('quarter', [Date]) = DATETRUNC('quarter', [Date | Max])
如果返回当前季度内的日期数据,为 TRUE。当数据集中包含每一天的数据时使用效果最好。如果数据中存在空值或是实时数据,请将 [Date | Max] 替换为 TODAY()。
在日历热图中,如果设定的日期值为 2024 年 9 月 25 日,则 2024 年 7 月-9 月的数据都是被高亮的。
Q2:Last Full Quarter 同年上一季度
计算字段 [LFQ] 表达式:
DATETRUNC('quarter', [Date]) = DATEADD('quarter', -1, DATETRUNC('quarter', [Date | Max] + 1))
如果返回与同年上一季度匹配的日期数据,则为 TRUE。这个计算适合在的“去年上一季度至今”(PQTD)计算中使用。
在日历热图中,如果设定的日期值为 2024 年 9 月 25 日,则 2024 年 4 月-6 月的数据都是被高亮的。
Q3:Last Full Quarter of Previous Year 去年上一季度
计算字段 [LQLY] 表达式:
DATETRUNC('quarter', [Date]) = DATEADD('quarter', -5, DATETRUNC('quarter', [Date | Max] + 1))
当返回去年与今年上一完整季度匹配的季度数据,则为 TRUE。
在日历热图中,如果设定的日期值为 2024 年 9 月 25 日,则 2023 年 4 月- 6 月的数据都是被高亮的。
Q4:Days into(any)Quarter 任意季初至某天
计算字段 [Date | DIQ] 表达式:
DATEDIFF('day', DATETRUNC('quarter', [Date]), [Date])
这个表达式将返回一个整数,表示从每季第一天至某天的天数。建议用在通过计算每个订单距离季度开始的天数,可以分析订单在季度内的时间分布,找出订单高峰期或低谷期。或者,可以将计算结果作为新的计算字段,用于进一步的分析或可视化。例如,可以创建一个字段表示订单是处于季度的月初、月中还是月末。
在日历热图中,如果设定的日期值为 2024 年 9 月 25 日,可以看到整个图表的标记都被高亮显示了。通过竖向对比,可以看到颜色的深浅用于表示每一天距离季初的天数累计差异。
Q5:Days into current quarter 当季首日至今
计算字段 [Current DIQ] 表达式:
DATEDIFF('day', DATETRUNC('quarter', [Date | Max]), [Date | Max])
与上个示例不同的是,用于表示每一天 [Date] 字段被替换成了已进行聚合的最新日期 [Date | Max],然后,计算每个分组(如果存在)中,最新日期距离所在季度开始的间隔天数。
如果你想分析客户或产品的活跃度,可以参考这个示例,计算他们每个季度最后一个订单距离季度开始的天数,看看是否在季度末期有集中下单的趋势;或者通过计算每个维度下最新日期距离季度开始的天数,分析不同维度下数据是否具有周期性。
在日历热图中,如果设定的日期值为 2024 年 9 月 25 日,可以看到整个图表的标记都被高亮显示了。但没有呈现颜色差异,因为最新日期是唯一的,所以累计天数也是唯一的。
Q6:Previous Quarter to date 上一季度至今
计算字段 [PQTD] 表达式:[LFQ] AND [Date | DIQ] <= [Current DIQ]
LFQ 是 Last Full Quarter(同年上一季度),Date | DIQ 是 Days into(any)Quarter(任意季初至某天),Current DIQ 是 Days into current quarter(当季首日至今)。
整体表达式的意思是,如果某日期属于上一个完整季度,且该日期在季度中的位置小于或等于当前日期在本季度中的位置,那么这个条件就为真。
通常用来比较两个季度(当前季度和之前的某个季度)中的日期,确保比较的是两个季度中相同或对应的天数。例如,如果今天是某个季度的第 20 天,那么表达式就会筛选出上一个完整季度中,和今天对应的前 20 天的数据。
在日历热图中,如果设定的日期值为 2024 年 9 月 25 日,可以看到 2023 年 Q2 前 87 天的数据都被高亮显示,这跟 2024 年 7 月 1 日至 9 月 25 日的天数差(87)是一样的。
日期计算示例:月度比较
M1:Current Month 当前月份
计算字段 [CM] 表达式:
DATETRUNC('month', [Date]) = DATETRUNC('month', [Date | Max])
此计算通常用于筛选或标记数据集中属于当前月份的所有记录。例如,如果你想筛选出所有发生在当前月份的数据点,或计算这个月内的总销售额。
👉 等号左侧:将 [Date] 字段中的日期值截断到“月” 粒度。也就是说,它会把日期“天”部分去掉,只保留“年”和“月”。例如,如果 [Date] 是 2024-09-15,将返回 2024-09。
👉 等号右侧:[Date | Max] 表示最新日期。假设最新日期为 2024-09-25,则会将这个日期截断到月份,也就是 2024-09。
👉 等号用于比较数据集中的某个日期所在月份是否与最新日期所在月份相同。也就是说,如果在同一个月,返回 TRUE,否则返回 FALSE。
在日历热图中,由于当前控件中所选的日期值为 2024 年 9 月 25 日,因此 2024 年 9 月的所有数据点为 TRUE,都被高亮显示。
TIPS:当数据集中包含每一天的数据时使用效果最好。如果数据中存在空值或是实时数据,请将 [Date | Max] 替换为 TODAY()。
M2:Last Full Month 上一个完整月份
计算字段 [LFM] 表达式:
[Date] < DATETRUNC('month', [Date | Max] + 1) AND [Date] >= DATEADD('month', -1, DATETRUNC('month', [Date | Max] + 1))
此计算的最终目的是标识数据集中是否存在上一个完整月份(即不包含当前月)的记录。通过组合使用几个日期函数,可准确定位到上一个完整月份的日期范围。
👉 AND 前:以最新日期为准,通过加上 1 天并截断到月份,就得到了下个月的起始日期。
👉 AND 后:嵌套了左侧表达式。表示将下个月的起始日期减去一个月,就得到了上个月的起始日期。
👉 当两个条件都满足时,返回 TRUE,即上个月第一天到最后一天的日期范围。
在日历热图中,由于最新日期值为 2024 年 9 月 25 日,而 9 月的数据显然是不完整的,那么上一个完整的月份就是 2024 年 8 月,因此 8 月的所有数据点都被高亮显示。
TIPS:通过巧妙运用日期函数,定义了以数据源最新日期为基准的动态月度范围,非常适合对近一个月数据进行分析的场景。此外,当数据集中包含每一天的数据时使用效果最好。如果数据中存在空值或是实时数据,请将 [Date | Max] 替换为 TODAY()。
M3:Last Full Month of Previous Year 去年上个完整月份
计算字段 [LMLY] 表达式:
[Date] < DATEADD("month", -12, DATETRUNC("month", [Date | Max] + 1)) AND [Date] >= DATEADD("month", -13, DATETRUNC("month", [Date | Max] + 1))
此计算基于最新日期值的上一个完整月份,识别上一年同期的所有数据。主要帮助分析师用于对比去年和今年相同时间段的数据表现。从结构上看,是在计算字段 [LFM] 基础上加了一层嵌套,且偏移数值不太一样。
👉 AND 前:先通过 DATETRUNC("month", [Date | Max] + 1) 得到最新日期下个月的起始日期。然后用 DATEADD("month", -12, ...) 将上述结果减去 12 个月,定位到去年对应月份的第一天。
👉 AND 后:跟左侧相同的结构,将偏移数值改为-13,定位到去年对应月份前一个月的第一天。
👉 将两个不等式结合起来且当两个条件都满足时,返回 TRUE,表示某一日期 [Date] 必须处于最新日期的前 12 个月到前 13 个月之间。
在日历热图中,由于最新日期为 2024 年 9 月 25 日,而 9 月的数据显然是不完整的,那么上一个完整的月份就是 2024 年 8 月,而去年同期的月份是 2023 年 8 月,因此被高亮显示。
TIPS:当数据集中包含每一天的数据时使用效果最好。如果数据中存在空值或是实时数据,请将 [Date | Max] 替换为 TODAY()。
M4:Days into month 某天至当月月初的天数
计算字段 [Date | DIM] 表达式:
DATEDIFF('day', DATETRUNC('month', [Date]), [Date])
计算每个日期距离所在月份的开始有多少天。换句话说,确定某天距离当月月初的天数间隔。这在时间序列分析中非常有用,尤其是当我们需要比较不同时间段内的进度时。
👉 DATETRUNC('month', [Date]):将日期 [Date] 截断到该月的第一天。例如,2024 年 9 月 15 日将被截断为 2024 年 9 月 1 日。
👉 DATEDIFF('day',...):计算从月初到具体日期 [Date] 之间的天数差值,返回结果是一个整数。如果 [Date] 是 2024 年 9 月 15 日,则返回 14,因为 9.1-9.15 之间有 14 天。
在日历热图中,[Date] 是一个动态值,因此所有标记都被高亮了。而颜色的深浅表示每一天距离当月月初的天数差,差值越大,颜色越深。
TIPS:如此,分析师就能更好地了解某一日期在时间范围中的相对位置,从而为时间进度分析、预算跟踪或进度比较提供支持。此外,此表达式也可被用于创建下文中提及的 [PMTD] 和 [MTDLY] 计算字段。
M5:Days into current month 本月月初至今的天数
计算字段 [Current DIM] 表达式:
DATEDIFF('day', DATETRUNC('month', [Date | Max]), [Date | Max])
跟上个示例的结构相同,不同的是日期 [Date] 被换成了最新日期 [Date | Max]。这意味着,由于数据集中的最新日期是唯一的,因此无论你对数据进行筛选或其他操作,本月月初至今的天数差都是唯一的。
在日历热图中,标记颜色是一致的。因为示例数据集中的最新日期是 2024 年 9 月 25 日,所以无论在哪个月,本月月初至今的天数始终恒定(24 天)。
TIPS:虽然这个计算字段本身是一个恒定值,但它在某些特定场景下还是有用的。
👉 可用来验证数据源中每个月的日期是否完整。如果计算结果与实际的天数不符,说明数据可能存在缺失。
👉 可作为其他计算的中间值。例如,计算某个月份的平均每日销售额。此外,这个表达式也可被用于创建下文中提及的[PMTD] 和 [MTDLY] 计算字段。
在图表中创建一条水平参考线,表示最新日期距离所在月份的天数。
M6:Previous Month to date 上一月份的相同天数
计算字段 [PMTD] 表达式:[LFM] AND [Date | DIM] <= [Current DIM]
结合这三个计算字段的作用(请自行翻看上文 M2、M4 和 M5 示例),我们可理解为:
👉 LFM(Last Full Month):最新日期的上一个完整月份(日期范围)
👉 Date | DIM(Days into month):每行日期记录与当月月初的天数差异(动态值)
👉 Current DIM(Days into current month):最新日期与当月月初的天数差异(恒定值)
👉 PMTD:先基于最新日期界定上个月的范围,再依照最新日期与月初的天数差,在上个月里找到相同天数的标记。
虽然有点绕,但结合日历热图来看,逻辑就会清晰很多。如下图,当前日期为 2024 年 9 月 25 日(距离月初的天数为 25)时,将高亮 2024 年 8 月 1 日到 25 日的数据。
TIPS:你可将此用于监控上个月与当前月份相同天数的业绩表现,或了解某些指标(如销售额)在不同月份的相同天数内是否有规律性变化等。
M7:Same Days in Current Month 不同月份的相同天数
计算字段 [SDCM] 表达式:[Date | DIQ] <= [Current DIQ]
结合这两个计算字段的作用(请翻看上篇中的 Q4 和 Q5 示例),我们可理解为:
👉 Current DIQ(Days into current quarter):最新日期与当季季初的天数差异(恒定值)
👉 Date | DIQ(Days into Quarter):每行日期记录与当季季初的天数差异(动态值)
👉 SDCM:判断某天距离所在季度的天数是否小于或等于最新日期距离所在季度的天数。
在日历热图中,最新日期是 2024 年 9 月 25 日,表达式就会以 25 天(9.1-9.25)为基准,找到其他月份中前 25 天的数据,并高亮标记显示。其他灰色点就是不匹配的数据。
TIPS:基准日期可以是 [Date | Max] 或 TODAY(),具体取决于你如何设置日期。此外,此示例与上一示例类似,只是对比月份从上个月变成了其他所有月份。所以,你可将其用于分析在不同月份的同样天数下,销售额、生产量等关键指标是否存在周期性变化。
M8:Month-to-Date of Same Month in the Previous Year 前一年的同月至今
计算字段 [MTDLY] 表达式:
DATETRUNC('month', [Date]) = DATEADD('year', -1, DATETRUNC('month', [Date | Max])) AND [Date] <= DATEADD('year', -1, [Date | Max])
确定数据集中,某个月份在前一年相同月份中对应的日期。主要用于对比分析当月与前一年同月的相同天数,以便进行年度趋势分析和数据比较。
👉 AND 前:等号左侧是将日期 [Date] 截断至月份级别;等号右侧是先将最新日期 [Date | Max] 截断到月份,后用 DATEADD 函数将月份向前推一年。整体用于判断 [Date] 所在的月份是否等于 [Date | Max] 在前一年的同一月份。
👉 AND 后:<= 右侧是将最新日期 [Date | Max] 向前推一年。整体用于检查 [Date] 是否小于或等于前一年中的对应日期。简单来说,这确保了筛选出的日期不能超过去年这个月的最新日期位置。
在日历热图中,2023 年 9 月 1 日至 9 月 25 日的数据被高亮,正好对应 2024 年 9 月同样时间范围内的数据,天数均为 25 天。
TIPS:适用于同比分析,例如对比去年同期至今的数据表现。
M9:Last 12 Full Months 过去 12 个完整月份
计算字段 [L12FM] 表达式:
DATETRUNC('month', [Date]) >= DATEADD('month', -12, DATETRUNC('month', [Date | Max]+1)) AND DATETRUNC('month', [Date]) < DATETRUNC('month', [Date | Max]+1)
用于确定数据集中过去 12 个月的完整月份,以便分析过去一年的数据表现,理解长期趋势和季节性变化。AND 连接了左右两个条件,需要同时满足,才会返回 TRUE。
👉 AND 前:DATETRUNC('month', [Date]) 用于将某一日期 [Date] 截断至月份级别,>=后的表达式用于计算得出最新日期 [Date | Max] 所在月份的前 12 个月。所以,整体用于定义过去 12 个月的起始日期。
👉 AND 后:< 前用于将某一日期 [Date] 截断至月份级别, DATETRUNC('month', [Date | Max]+1) 则基于最新日期所在月份往后推一个月。所以,整体用于定义过去 12 个月的结束日期。
最后,将两个不等式结合起来,就表示当前日期必须处于最新日期的前 12 个月内,但不包括最新日期所在的那个月。这样,分析师可聚焦于过去一整年的数据进行分析,且不受当前月份不完整数据的干扰。
在日历热图中,最新日期是 2024 年 9 月 25 日,在 2024 年 9 月之前那 12 个月(即 2023.9 - 2024.8)的数据都被高亮显示。
TIPS:这个计算在实际应用中非常有价值,尤其是在评估年度业绩、规划预算和制定策略时,能提供可靠的历史数据支持。
M10:Last 12 Months 过去 12 个月(不完整)
计算字段 [L12M] 表达式:
DATETRUNC('month', [Date]) >= DATEADD('month', -11, DATETRUNC('month', [Date | Max]+1)) AND DATETRUNC('month', [Date]) <= [Date | Max]
与上个示例不同,这个计算的作用是标识出数据集中过去 12 个月的日期,包含了 11个完整的月份数据以及当前月份的不完整数据。
在日历热图中,2023 年 10 月至 2024 年 9 月的数据均高亮显示。通过这种方式,分析师能够获得一个完整且具有连续性的 12 个月数据集,从而更好地理解过去一年的业务表现。
TIPS:在需要实时跟踪和分析过去 12 个月数据,且确保分析能覆盖到最新月份时,这个计算非常有用。
M11:Month of Quarter 季度中的月份顺序
计算字段 [MOQ] 表达式:((DATEPART('month', [Date]) -1) % 3) + 1
用于计算某个日期所属的月份在当季中的位置,因此结果是一个整数。举例来说,每个季度有三个月,则会返回 1、2 或 3,分别表示该月份是当季的第几个月。
表达式的结构也很好理解,共包含三层:
👉 DATEPART('month', [Date]) 用于提取日期的月份,返回数字 1-12。
👉 (DATEPART('month', [Date]) - 1) % 3 表示先将月份数减去1,让 1-12 月变为 0-11。然后取这些值除以 3 的余数,这个余数会是 0、1 或 2,对应季度中的第 1、2、3 个月。
👉 +1:最后将结果加 1,以确保返回值为 1、2 或 3。
如下图中的颜色对比可知,如果某个日期是 4 月,则会返回 1,因为 4 月是 Q2 的第一个月;如果是 5 月则返回 2,以此类推。
TIPS:对于需要分析季度周期或季度内月度表现的情况非常有用。通过这个表达式,分析师能够更灵活地处理季度数据,并可在季度层级上展开细化分析。
日期计算示例:周比较
W1:Current Week 当前周
计算字段 [CW] 表达式:
DATETRUNC('week', [Date]) = DATETRUNC('week', [Date | Max])
此表达式通过比较 [Date] 日期和 [Date | Max] 最新日期的周截断结果,判断两个日期是否在同一周内。如果两者的周开始日期一致,那么返回 TRUE,表示这个日期在当前周。
👉 DATETRUNC('week', [Date]):将 Date 字段中的日期截断到最近的一个周的开始,类似于每周一的日期。
👉 DATETRUNC('week', [Date | Max]):同样的处理逻辑应用到 [Date | Max],这个值表示数据集中日期的最大值(最新日期或者是手动设定的最大日期)。
从日历热图上,2024 年 9 月 25 日是最新日期,因此 2024 年 9 月 22 日为起始日期的这周被高亮。在实际应用中,你可以将此计算用于分析当前周的趋势或业绩表现。
TIPS:当数据集中包含每一天的数据时使用效果最好。如果数据中存在空值或是实时数据,请将 [Date | Max] 替换为 TODAY()。
W2:Last Full Week 上一个完整周
计算字段 [LFW] 表达式:
DATETRUNC('week', [Date]) = DATEADD('week', -1, DATETRUNC('week', [Date | Max] +1))
检查 [Date] 是否位于最后一个完整周内。通过比较 [Date] 和上一个完整周的开始日期,如果它们相同,则返回 TRUE,表示该日期属于最后一个完整周。
👉 DATETRUNC('week', [Date]):将 [Date] 字段截断到所在周的第一天。也就是说,不管 [Date] 指向的是周中的哪一天,都会返回该周的周一。
👉 DATETRUNC('week', [Date | Max]+1):将数据集最新日期截断到所在周的第一天;+1 表示偏移到下一周,即得到“下一周的周一”。
👉 DATEADD('week', -1, ...):在“下一周的周一”基础上,减去一周。这样就得到了“上周的周一”。
在日历热图中,如果 [Date | Max] 为 2024 年 9 月 25 日,那么 2024 年 9 月 15 日到 9 月 21 日的这一周被高亮。在实际分析场景中,此计算可帮助你分析上周的指标表现或趋势。
TIPS:在很多分析场景中,“最后一周”并不是指包含数据集最后一个日期的那一周,而是指“数据集所覆盖的最后一个完整周”。比如,如果数据集的最后一天是周三,那么“最后一周”应该指的是包含这个周三的前一周。
此外,这种计算方式可以避免由于数据集最后一天是周日、周一等情况而导致的“最后一周”判断错误。
W3:Same Week of Current Date for the Previous Year 去年同一周
计算字段 [LWLY] 表达式:
DATETRUNC('week', [Date]) = DATETRUNC('week', DATEADD('year', -1, DATEADD('week', -1, DATETRUNC('week', [Date | Max] +1))))
此表达式的作用是找到与当前日期一年前的同一周,并检查给定的 [Date] 是否位于这个一年前的周内。如果 [Date] 位于一年前的同一周内,返回 TRUE。简单来说,整个表达式可以基于最新日期的上一个完整周找出在去年同期(同一周)的数据。
由于表达式有过多偏移值和嵌套,所以我们假设 [Date | Max] 是 2024 年 9 月 25 日,然后再逐一解释表达式的各个部分。
👉 等号右侧最内层:即 DATETRUNC('week', [Date | Max] + 1)。其中,如果 [Date | Max] 是 2024 年 9 月 25 日,则将其加 1 天,即 2024 年 9 月 26 日。DATETRUNC('week'...) 表示会将 2024 年 9 月 26 日截断到所在周的起始日期,即 2024 年 9 月 23 日。
👉 等号右侧外一层:即 DATEADD('week', -1,...)。由于最内层的结果是 2024 年 9 月 23 日,所以中间层的含义将最内层结果向前推 1 周,即 2024 年 9 月 16 日。
👉 等号右侧外二层:即 DATEADD('year', -1, …)。表示将外一层的结果日期(2024 年 9 月 16 日)向前推 1 年,结果是 2023 年 9 月 16 日。
👉 等号右侧最外层:即 DATETRUNC('week', …)。对 2023 年 9 月 16 日 进行周截断,得到 2023 年 9 月 11 日(去年同一周的起始日期)。
👉 等号左侧表达式:即 DATETRUNC('week', [Date]) 要检查的是 [Date] 是否与 2023 年 9 月 11 日所在的周相匹配。
因此在日历热图中,2023 年 9 月 11 日所在的那一周被高亮显示,对应的是 2024 年 9 月 25 日所属那一周(即 2024 年 9 月 23 日开始的一周)。此外,由于 2023 年 9 月 11 日并非周起始日,所以去年同周的计算相比于去年同一个月或同一季度来说是更为复杂的。
TIPS:在时间序列分析中,“去年同期”通常指与今年同一周的去年对应的时间段。通过这种方式计算,可以准确地找到去年对应的周,而不需考虑闰年或不同月份天数的影响。
在实际场景中,可以用来计算当前周的某个指标相对于去年同期的增长率,或者用来分析数据的季节性变化趋势,找出与历史同期数据偏差较大的异常值。
W4:Same Week Number of Last Full Week for the Previous Year 去年第几周
计算字段 [LWNumLY] 表达式:
DATEPART('week', [Date]) = DATEPART('week', DATEADD('week', -1, DATETRUNC('week', [Date | Max] +1))) AND DATEPART('year', [Date]) = DATEPART('year', DATEADD('week', -1, DATETRUNC('week', [Date | Max] +1))) -1
相比 [LWLY] 示例,这个表达式增加了一个条件,目的是根据周编号(即第几周)更精确地判断数据是否属于“去年同期”。具体来看,通过找到最新日期在所在年份的周编号(即第几周),来查找数据集中上一年对应的相同完整周期。返回 TRUE 表示匹配。
由于表达式有过多偏移值、嵌套和运算符,所以我们假设 [Date | Max] 最新日期是 2024 年 9 月 25 日,然后再逐一解释表达式的各个部分。
👉 AND 前:在最新日期设定下,[Date | Max] + 1 就是 2024 年 9 月 26 日。那么 DATETRUNC('week', [Date | Max] + 1) 是将 2024 年 9 月 26 日截断为所在周的开始日期。如果一周从周一开始,那么结果是 2024 年 9 月 23 日(即该周的周一)。由于上一步结果是 2024 年 9 月 23 日,所以 DATEADD('week', -1, …) 会将这一日期往前推一周,即 2024 年 9 月 16 日。如果在外层再加上 DATEPART('week', …),就会返回 2024 年 9 月 16 日所在的 ISO 周编号。根据 ISO 8601,周数从 1 到 52 或 53 不等,这里的结果是第 38 周。
👉 AND 后:参考之前的解释,这部分表达式是对同一日期 2024 年 9 月 16 日进行年份提取。返回结果是 2024 年。
总的来看,AND 前的等式是检查 [Date] 是否与 2024 年 9 月 16 日属于同一周,即 ISO 周编号是否相等。如果 [Date] 是 2023 年中的某一周,则它的周编号也要与 2024 年 9 月 16 日 的周编号一致。AND 后的等式是检查 [Date] 所在年份是否为 2024 年的前一年。
结合日历热图进行验证,2023 年第 38 周(2023 年 9 月 17 日至 9 月 23 日)被高亮。它匹配了数据集中基于最新日期(所在周不完整)推算出来的上一个完整周(2024 年 9 月 18 日至 9 月 24 日)的编号,即 2024 年第 38 周。
W5:Last 52 Full Weeks 最近 52 个完整周
筛选出数据集中符合条件的日期,即过去 52 周内的所有日期标记。根据 ISO 8601,这通常用于计算近一年( 52 周或 53 周)的周趋势数据。
👉 AND 前:首先 DATETRUNC('week', [Date | Max] + 1) 将最新日期往后推一天,然后将其截断到所在周的第一天。DATEADD('week', -1, ...) 从上述周的开始时间向前偏移一周,得出上一个完整周的结束时间。整个不等式用于确保 [Date] 在上一个完整周之前或等于上一个完整周的最后一天。
👉 AND 后:确保 [Date] 在从当前日期的前 52 周内。通过将 [Date | Max] 最新日期偏移为下一周的第一天并向前移动 52 周,从而计算出过去一年的周起始日期。
在日历热图中,最新日期是 2024 年 9 月 25 日,因此从上一个完整周的起始日期(2024 年 9 月 16 日)往回数 52 个完整周之间的数据标记(2023 年 9 月 25 日到 2024 年 9 月 21 日)都会被高亮显示。
W6:Last 13 Full Weeks 最近 13 个完整周
筛选出过去 13 个完整周内的数据。根据 ISO 8601,你可将其理解为用于查看最近一个季度内的周数据。此外,[L13W] 和 [L52] 这两个计算字段的表达式结构基本相同,都是用于选取一段时间范围内的完整周。唯一的区别在于回溯的周数不同。
在日历热图中,如果最新日期是 2024 年 9 月 25 日,那么 2024 年 6 月 24 日到 2024 年 9 月 21 日之间的所有完整周都高亮显示了。
TIPS:你可根据不同的需求来调整回溯的周数,比如将 13 改为 4、26 等,就可以选取不同长度的时间段。
W7:Previous 13 Full Weeks 上一个完整的 13 周
从字段名字上看,如果最新日期是 2024 年 9 月 25 日,那么 Last 13 Full Weeks [L13W] 选取的是最近的 13 周,也就是过去 1 周到 13 周的完整周范围。
如果以 13 个完整周为一个周期,那么 Previous 13 Full Weeks [P13W] 就是找到上一个周期,也就是从过去 14 周到 26 周的完整周范围(不包括最近的 13 周)。
为了方便理解,我们基于最新日期为 2024 年 9 月 25 日的假设,逐步解释表达式的含义:
👉 DATEADD('week', -14, DATETRUNC('week', [Date | Max] + 1)):从 [Date | Max] 所在周的起始(2024 年 9 月 23 日)往回推 14 周,得到 2024 年 6 月17 日所在周的开始日期。
👉 DATEADD('week', -26, DATETRUNC('week', [Date | Max] + 1)):从 [Date | Max] 的下一周往回推 26 周,得到 2024 年 3 月 24 日所在周的开始日期。
👉 AND 前后两个不等式是确保 [Date] 的数据范围(13 个完整周)不晚于 2024 年 6 月 23 日,且不早于 2024 年 3 月 25 日,从而帮助你查看过去更长一段时间的数据趋势。
日历热图中的蓝色高亮区域验证了这一计算结果。
W8:Last 13 Full Weeks for the Prior Year 去年同期(最近 13 个完整周)
此计算字段的作用是以最新日期为基准,先算出最近 13 个完整周的范围,再找出上一年相对应的数据范围。这有助于从年度级别比较同一个周期范围的数据趋势。
在日历热图中,最新日期为 2024 年 9 月 25 日,则整个表达式将获取上一年的相同时间段,即从 2023 年 6 月 17 日到 2023 年 9 月 9 日,对应的是最新日期最近 13 个完整周(2024 年 6 月 17 日到 2024 年 9 月 9 日)的范围。
W9:Prior Year-to-Last-Full Week 去年年初至最后一个完整周
计算字段 [WTDLY] 表达式:
[Date] < DATETRUNC('week', DATEADD('year', -1, DATETRUNC('week', [Date | Max] +1))) AND YEAR([Date]) = YEAR(DATEADD('year', -1, [Date | Max] + 1))
基于最新日期,找出最新日期所在年份的起始日期至最近一个完整周的时间范围,然后再从去年找出对应时间范围的数据。可以将其理解为同期数据对比的一种示例,帮助你查看去年的同一时间段内发生的情况。
假设 [Date | Max] 最新日期是 2024 年 9 月 25 日,那么整个表达式的拆解如下:
👉 AND 前:DATETRUNC('week', [Date | Max] + 1) 将最新日期后移一天,即 2024 年 9 月 26 日。然后通过 DATETRUNC('week', ...) 截取到这一周的开始,即 2024 年 9 月 23 日。DATEADD('year', -1,...) 将 2024 年 9 月 23 日往前推一年,得到 2023 年 9 月 23 日。接下来,DATETRUNC 会截取 2023 年 9 月 23 日所在周的开始,即 2023 年 9 月 18 日。因此,这个不等式的意思是,[Date] 日期要在 2023 年 9 月 18 日之前。
👉 AND 后:DATEADD('year', -1, [Date | Max] + 1) 会将 2024 年 9 月 26 日往前推一年,得到 2023 年 9 月 26 日,然后 YEAR 函数会将结果截断为 2023 年。因此,[Date] 日期所在范围必须是 2023 年。
结合两个条件,计算结果是 2023 年内且在 9 月 18 日之前(即 2023 年 1 月 1 日至 2023 年 9 月 17 日)的所有数据点。下方日历热图中的高亮标记可以很好地验证这一结果。
W10:Week Number of Each Month 月份中的周数次序
计算字段 [Week No | Month] 表达式:
DATEPART('week', [Date]) - {FIXED DATETRUNC('month', [Date]) : MIN(DATEPART('week', [Date]))} + 1
计算日期(动态值)属于每个月中的周编号(第几周),确保从月的第一周开始计数,数值范围是 1 到 6。通过此表达式,你可为每个月中的周次进行分类和标记。这在分析月度数据时非常有用,比如按每月的周数分析销售或事件数据。
👉 减号前的 DATEPART('week', [Date]) 会获取给定日期的周编号(在整年的第几周)。
👉 减号后是 FIXED 详细级别表达式,用于获取每个月的第一周。DATETRUNC('month', [Date]) 将日期截断到该月的开始。MIN(DATEPART('week', [Date])) 则返回在当前月份中,最早一周的周编号。
👉 整个表达式是先减后加。通过 DATEPART('week', [Date]) 减去该月中最早一周的周编号,再 + 1 (为确保从 1 开始计数,使第一个周数从 1 开始递增)。这样可得出指定日期相对于该月的第几周。即使 1 月的第一周跨月,计算也能准确返回当前日期相对于该月的周次编号,结果范围通常在1 - 5(或 6,视月份天数和周起始日而定)之间。
从竖向查看下方日历热图,由于 [Date] 日期是个动态值(非恒定值),所以每个月每一周的颜色都是按周次逐渐加深的,符合周数递增的逻辑。
日期计算示例:日比较
D1:Current Day 当前日期
计算字段 [CD] 表达式:
DATETRUNC('day', [Date]) = DATETRUNC('day', [Date | Max])
这个计算字段会返回布尔值 TRUE 或 FALSE。当 [Date] 是数据集中最新的那一天时,它会返回 TRUE,否则返回 FALSE。可以用来筛选或高亮数据集中最新日期的数据行。
DATETRUNC 是 Tableau 中用来将一个日期字段截断到指定时间粒度的函数。通过将 [Date] 和 [Date | Max] 字段截断为天,并对两个值进行等号比较。当 [Date] 与 [Date | Max] 的截断值相等时,返回 TRUE。
在日历热图中,2024 年 9 月的一个标记被高亮显示,即数据集中的最新日期 2024 年 9 月 25 日。
D2:One week prior of Last Day 一周前的日期
计算字段 [LDLY] 表达式:
[Date] = DATEADD('week', -1, DATETRUNC('day', [Date | Max]))
判断 [Date] 是否等于最新日期 [Date | Max] 前一周的日期。如果是,则返回 TRUE,否则返回 FALSE。可用于筛选或标记最新日期前一周的记录,以便比较 7 天前的数据变化。
DATEADD('week', -1, ...) 表示将日期减去一周。因此,等号右侧表达式会将 2024 年 9 月 25 日前移 7 天,得到日期 2024 年 9 月 18 日。在日历热图中,这一天被高亮显示,与计算逻辑吻合。
D3:Weekdays Only 常规工作日
计算字段 [is_weekday] 表达式:DATEPART('weekday', [Date]) IN(2, 3, 4, 5, 6)
判断 [Date] 是否是工作日(星期一至星期五)。如果是,返回 TRUE,否则返回 FALSE。它可以用于筛选或标记数据集中工作日的数据。
👉 DATEPART('weekday', [Date]) 的作用是返回 [Date] 对应的第几周。在 Tableau 中,星期天的值为 1(周日是一周的开始),星期一至星期六的值分别为 2 到 7。
👉 IN (2, 3, 4, 5, 6) 是对结果的筛选条件,表示只选择工作日。2 代表星期一,3 代表星期二,以此类推,6 代表星期五。因此,IN 的作用是筛选出星期一至星期五的记录。
在日历热图中,所有高亮的日期都是工作日,表示表达式成功筛选出了工作日的数据,而周末的数据未被高亮显示。
D4:Weekends Only 周末两天
计算字段 [is_weekend] 表达式:DATEPART('weekday', [Date]) IN(1, 7)
跟计算常规工作日的方法一样,上个示例的表达式结构还适用于筛选周末的日期记录。
在日历热图中,高亮显示的日期都是周六和周日。这表明计算字段成功筛选出所有周末数据。
D5:Most Recent 30 Days 最近 30 天
计算字段 [L30D] 表达式:DATEDIFF('day', [Date], [Date | Max]) < 30
精准筛选出数据集最新日期 [Date | Max] 前 30 天内的所有记录。从场景来看,可用来筛选最近 30 天的数据,分析最新的业务活动;或动态分析 30 天内的数据,进行实时趋势追踪。
DATEDIFF('day', [Date], [Date | Max]) 用于计算 [Date] 与 [Date | Max] 之间的天数差值。具体来说,'day' 表示以“天”为粒度单位来计算差异。再根据条件 < 30,那么返回的日期会以最新日期 [Date | Max] 为基准,找出最近的 30 天以内的数据。
在日历热图中,2024 年 8 月 27 日至 9 月 25 日的数据被高亮,正是最近 30 天的数据,与计算预期结果一致。
D6:Previous 30 Days Prior 前 30 至 60 天
计算字段 [P30D] 表达式:
DATEDIFF('day', [Date], [Date | Max]) >= 30 AND DATEDIFF('day', [Date], [Date | Max]) < 60
筛选出数据集最新日期 [Date | Max] 前 30-60 天内的所有记录,可帮助用户查看过去 1-2 个月之间的数据,便于分析这个时间段内的特定数据表现。
👉 AND 前:这一部分是用来确保 [Date] 距离 [Date | Max] 的差距至少是 30 天,意味着从最新日期往前推至少 30 天开始计算。
👉 AND 后:这一部分用来限制返回的日期距离 [Date | Max] 的差距在 60 天内。因此,筛选出的日期范围会在前 31 天到前 60 天之间。
在日历热图中,由于最新日期是 2024 年 9 月 25 日,因此高亮显示的正是 2024 年 7 月 28 日至 8 月 26 日之间的所有日期,与计算得出的范围一致。
D7:Third Thursday of the Month 每月第三个星期四
计算字段 [3ThM] 表达式:
[Date] = DATEADD('week', 2, {FIXED DATETRUNC('month', [Date]) : MIN(IF DATEPART('weekday', [Date]) = 5 THEN [Date] END)})
通过找到每个月的第一个星期四,然后向前推两周,从而准确定位到第三个星期四。适合分析定期发生在每月第三个星期四的会议或事件,或筛选出与特定周几相关的日期,便于周期性数据分析。
由于这个示例嵌套了好几个函数表达式,因此我们拆解一下:
👉 FIXED DATETRUNC('month', [Date]):将 [Date] 日期截断到月份。FIXED LOD 表达式的作用是确保计算仅基于“月份”维度进行,并忽略视图中的其他维度。这意味着即使视图中有如周、年等其他维度,FIXED 也会强制计算聚合值只在每个月的范围内。
👉 假设 DATEPART('weekday', [Date]) = 5,5 代表星期四,则 MIN (IF DATEPART(... THEN [Date] END) 会查找当前月份中所有星期四的记录,并返回最早(第一个)的星期四。
👉 DATEADD('week', 2, ...):将第一个星期四后移两周,即返回当月第三个星期四的日期。
日期计算示例:其他粒度
O1:Decade 年代(十年)
计算字段 [Decade] 表达式:INT(YEAR([Date])/10) * 10
将日期归类到对应的年代(10 年为单位)区间,助你在分析中按年代粒度进行数据聚合、分组和可视化。拆解来看:
👉 首先用 YEAR([Date]) 提取 [Date] 字段的年份。然后除以 10,得到年份的十进制表示。例如,2024/10 得到 202.4。这是为了方便截取年份的前几位,表示该年份属于哪个年代。
👉 然后,用 INT() 函数取整,会将 202.4 截断为 202,舍去小数部分。最后再乘以 10,得到完整的十年。例如,202 * 10 = 2020。这意味着如果 [Date] 日期为 2024 年 9 月 25 日,计算结果将返回 2020,表示这个日期属于 2020-2029 这十年。
在日历热图中,示例数据范围为 2022 年 1 月 1 日至 2024 年 9 月 25 日,没有横跨 2020年-2029 年,因此所有符合条件的标记都被高亮显示了。
O2:Create Date 创建日期
计算字段 [YM] 表达式:MAKEDATE([Year], [Month], 1)
用于将年份和月份重新组合成一个具体日期。例如,在时间序列分析中,可能缺失了某一行记录的日期值,你可以用它来补充数据。
通过给定的年份、月份和数字,MAKEDATE() 函数会在 Tableau 中生成一个新的完整日期,返回的日期格式为 YYYY-MM-DD:
[Year]:代表年份的字段,一般是数据集中的年份数据(如 2024);
[Month]:代表月份的字段,表示从 1-12 之间的数字;
数字: 可以随意指定,表示你想要生成的日期属于该月的第几天。
日期计算示例:表计算方法
T1:Last 13 Weeks 最近 13 周
计算字段 [L13W] 表达式:LAST() < 13
适合基于视图中的日期粒度展示固定的时间窗口(如最近 13 周、12 个月等),可以动态调整数据范围,避免手动调整日期。
👉 LAST() 是一个表计算函数,用来返回当前视图中距离最后一个数据点的偏移量。LAST() 的值从 0 开始表示最后一个数据点,-1 表示倒数第二个数据点,依此类推。
👉 LAST() < 13 表示从最后的数据点往前数 13 个数据点。将其拖入筛选器,返回 TRUE,即返回最后 13 周的数据,适用于你要展示最近几周或几个月的趋势。其中,偏移量可以按需要自定义。
在时序分析条形图中,因为日期粒度是周,所以会筛选显示最近 13 周的度量表现。
T2:Monthly YoY Comparisons 月度同比差异
通过将每个月的数据与去年同一月份进行对比,可以观察和分析两个时间点的变化情况。月同比通常用于识别长期趋势、季节性变化或评估年度增长或下降的表现。
如果使用表计算方法实现月同比分析,则需要先创建以下计算字段:
计算字段 [L12Y] 表达式:LAST() < 12
表示仅返回最近 12 个月的度量数据。在视图中使用时,需要将此计算字段放置在筛选器中,以显示仅为 TRUE 的数据。
计算字段 [MoM%] 表达式:
SUM([Measure]) - LOOKUP(ZN(SUM([Measure])), -12) / ABS(LOOKUP(ZN(SUM([Measure])), -12))
计算当前值与前一年同月值之间的百分比变化,主要用于月度同比分析。返回的结果是一个浮点类型的数值,放在图表中展示时可以设置为百分比格式。
👉 SUM([Measure]):[Measure] 是一个度量字段(如销售额、用户数等)。通过对当前范围内的 [Measure] 进行求和操作,计算出当月的度量值。
👉 LOOKUP(ZN(SUM([Measure])), -12):LOOKUP() 函数用于获取表中前后一定偏移的值。-12 表示取当前行向上偏移 12 行的数据。在月为粒度的视图中,相当于取一年前同月的 度量值。ZN() 函数会将空值(NULL)转换为 0,避免计算过程中出现空值导致错误。
👉 ABS() 函数:取绝对值,确保不会因为前一年度量值是负数而导致百分比计算出错。
如果要在视图中显示最近 12 个月的月同比分析,可参考以下步骤:
先将日期字段拖到列,按月显示;
将度量字段和 [MoM%] 计算字段拖到行;
将 [L12Y] 计算字段放入“筛选器”卡中,并选择 True。
上图显示了从 2023 年 10 月到 2024 年 9 月(最近 12 个月)的百分比差异。
还想深入了解其他日期计算的方法?立即点击观看《快速上手 Tableau 计算功能》回放视频吧~
推荐阅读:更多 Tableau 计算使用技巧