Power BI 提供多種工具來執行以時間為基礎的計算,這些計算依賴於自動日期表或您新增的日期表。
建議您使用 行事曆型時間智慧 (預覽版), 因為它提供最佳效能和最高範圍的彈性,以符合任何行事曆。
下表比較了提供的三個工具:
| Tool | 需要的設定工作 | 易於管理 | 靈活性 | 註釋 |
|---|---|---|---|---|
| 自動日期/時間 | 幾乎為零 | 硬 | 低 | 由於創建了多個隱藏日期表而增加模型大小 |
| 經典時間智能 | 適中 | 容易 | 低 | 需要建立日期表,假設公曆或移位公曆,在某些特定案例中會遇到效能問題 |
| 以行事曆為基礎的時間智慧 | 高 | 適中 | 高 | 建議建立日期表,彈性最高,效能最佳,但設定成本增加 |
備註
我們建議不要使用替代時間智慧技術,特別是那些涉及在日期表中添加額外列以計算偏移量的技術,但特定用例除外。 雖然這些方法可能會因其簡單的 DAX 公式而吸引初學者,但它們往往會不必要地膨脹語義模型。 隨著資料集的成長,這種膨脹可能會導致資料重新整理速度變慢,並降低報表效能。
自動日期/時間
自動日期/時間功能會自動為資料模型中的每個日期欄位建立隱藏的日期表格。 如需此自動行為的詳細資訊,請參閱 在 Power BI Desktop 中套用自動日期/時間。
備註
雖然自動日期/時間是簡單模型的便利選項,但不建議用於更複雜的案例和較大的模型。 對於這些模型,最好建立專用表格以獲得更大的靈活性。
新增日期表格
對於大多數模型,建議新增日期表(或在某些情況下新增更多)。 許多資料分析師更喜歡建立自己的日期表,這很好。
有多種方式可以建立這類表格,包括:
- Power Query M。您可以使用 List.Dates 函數。 本文檔稍後將提供示例。
- DAX 指數。 您可以使用 CALENDAR 或 CALENDARAUTO 函數來產生基本計算日期表格。 您也可以使用更進階的 DAX 陳述式來建立日期資料表。 本文檔稍後將提供示例。
- 外部工具。
- 從來源載入,例如來源系統、檔案或其他 Power BI 語意模型。
哪個選項最適合您取決於各種因素,並且超出了本教程的範圍。
使用基於時間的計算
假設您未使用 自動日期/時間,有兩種替代方式可在 Power BI 中使用時間智慧型函式 來執行以時間為基礎的計算:
- 經典的時間智能。 最簡單的選項,效果良好,適合用於公曆或移位公曆,但對於結構不同的日曆或基於週的計算,其靈活性有限。
- 行事曆型時間智慧 (預覽版)。 較新的選項,但需要一些額外的努力來設置。 但是,它還為您提供更好的性能、使用非公曆的更大靈活性以及執行基於週的計算的能力。
備註
您需要 將表設定為日期資料表,以適應特定場景。
經典時間智能
此選項要求您在模型中有一個日期表,並 據此進行設定。 之後,您可以使用 時間智慧功能 並參考您的日期表。 例如,如果您的模型中有一個名為「 日期 」的日期表格,並將其設定為日期表格,其中包含「日期」資料行,則您可以使用:
SAMEPERIODLASTYEAR ( 'Date'[Date] )
雖然這是一種快速而簡單的方法,但與 基於日曆的方法相比,有許多缺點:
- 它需要您設定日期表
- 它僅適用於至少具有一個專用日期表的模型
- 使用的日期欄在第一個日期和最後一個日期之間不應有遺漏的日期。 如果第一個日期和最後一個日期之間有任何遺漏日期,則會拋出錯誤。
- 它的彈性較差,因為它針對傳統公曆或調整過的公曆(例如從 7 月 1 日開始但仍遵循公曆的會計年度)進行了最佳化。
- 它不提供以週為基礎的計算
- 在特定案例中,以時間為基礎的計算效能不佳。
備註
我們建議您使用 增強的、以日曆為基礎 的方法。
行事曆型時間智慧 (預覽版)
行事曆是新增至表格的中繼資料定義,以指出該表格中的哪些欄代表哪些時間屬性。 您可以在模型中的任何表格上定義一或多個行事曆。 在模型中定義行事曆之後,您可以在時間智能函數中參考行事曆。 例如,以下是如何使用定義的 會計行事曆計算銷售額的年度累計總計:
TOTALYTD ( [Sales], 'Fiscal Calendar' )
以行事曆為基礎的時間智慧的優點
基於日曆的時間智能的主要優點是:
適用於任何日曆
日曆讓您可以完全靈活地決定如何以年、季度、月和週劃分時間。 例如,您可以定義遵循下列模式的行事曆:
- Gregorian
- 位移曆法公曆
- 零售(445、454、544 模式)
- 13個月
- 月球的
考慮到 Power BI 沒有對您的行事曆結構做任何內建假設,其可能性是無窮無盡的。 以行事曆為基礎的時間智慧不會對基礎日期做出任何假設。 所有計算都完全使用原樣的基礎資料。
稀疏日期
傳統時間智慧 要求提供的日期欄必須完整 - 如果在第一個和最後一個日期之間存在遺漏的日期,將會產生錯誤。 以行事曆為基礎的時間智慧函數沒有這樣的要求。 相反,他們直接運行日期,保持其原始狀態。 雖然我們仍然建議您擁有完整且專用的日曆表,但您不再需要擁有它。 例如,如果您所有的零售商店都在週末關閉,您可以跳過週末,因為它們沒有任何銷售。 假設您的週末是星期六和星期日,您現在可以使用PREVIOUSDAY,搭配依據沒有週末項目的表格製作的行事曆,從星期一直接跳到星期五。
以週為基礎的計算
行事曆為基礎的時間智慧直接提供以週粒度運作的 DAX 函數。 例如,可以使用以下命令直接 TOTALWTD計算本週至今的總計:
TOTALWTD ( Expr, CalendarName )
效能改善
在將日曆型時間智慧函數與其傳統對應函數進行比較時,某些場景可能會表現出改進的效能。 例如,使用 TOTALYTD ( ..., CalendarName ) 進行年初至今的計算,並依週分組的視覺化圖表,通常會比使用其傳統對應專案 TOTALYTD ( ..., TableName[DateColumnName] ) 來執行時更快。 如需深入瞭解為什麼會發生這種情況,請參閱 內容清除 一節。
啟用增強型 DAX Time Intelligence 預覽
若要開始使用,您必須先啟用 增強型 DAX 時間智慧 預覽功能。
- 在 Power BI Desktop 中,移至 [檔案 > ] [選項和設定 > ] [選項 > ] [預覽功能]。
- 選取 增強型 DAX 時間智慧 預覽。
- 選取 [確定]
- 重新啟動 Power BI Desktop
管理行事曆
若要管理行事曆,請以滑鼠右鍵按一下包含行事曆或您要定義行事曆的表格,然後選擇 [行事曆選項] ,或在選取表格之後,在 [表格工具] 功能區中選取 [行事曆選項 ]:
或者,您可以使用外部工具或 TMDL 視圖 來定義行事曆。 如需詳細資訊,請參閱 TMDL 指令碼。
行事曆也會顯示在 模型總管 中定義行事曆的資料表下:
行事曆選項畫面
行事曆選項畫面會顯示所選表格上定義的行事曆。 您可以在這裏:
- 選取 [新增行事曆] 來建立新行事曆
- 選取 [編輯] 來編輯現有行事曆
- 選取 [刪除] 來刪除現有行事曆
- 選取[標示為日期表格] 將 表格設定為日期表格
指派欄類別
定義行事曆涉及為其命名並將列指派給類別。 每個類別代表一個時間單位,並且可以使用特定的 欄類別 。 您至少需要將一個主要欄指派給類別,才能儲存行事曆。 每個類別都應該有一個 主要資料行,而且可以有零個或多個相關聯的資料行。 每當與類別相關聯的任何資料行位於內容中時,Power BI 就會知道它們呈現的時間單位。 此外,TOTALMTD Power BI 在某些函式中,會使用主要資料行來對應至參考行事曆中的相關類別,以執行請求的計算。 若要將資料行指派給類別,請從 [ 新增類別 ] 功能表中選取類別,然後選取主要和選用的相關資料行。
可用的欄類別
下表顯示可用的類別。 此表格也提供公曆的範例值及基數。
類別分為兩組:
- 完成。 指派給「完整類別」的欄中的資料足以唯一識別時段。
- 部分。 指派給 [部分類別] 的資料行中的資料不足以唯一識別時段。
| 類別 | Description | 類型 | 公曆中的基數範例 | 公曆中的欄位值範例 |
|---|---|---|---|---|
| 年 | 年份 | 完成 |
Y = 年數 |
2024, 2025 |
| 季度 | 包括年度在內的季度 | 完成 | 4*Y |
2024 年第 1 季、2025 年第 2 季 |
| 全年季度 | 一年中的季度 | 部分的 | 4 |
年度第 1 季、第一季、Q1、第 2 季度 |
| 月 | 包含年份的月份 | 完成 | 12*Y ≤ value ≤ 13*Y |
2023 年 1 月, 2024 年 2 月 |
| 一年中的月份 | 一年中的月份 | 部分的 | 12 |
一月、年 11 月、YM11、M11、11 |
| 季度月份 | 本季度的月份 | 部分的 | 3 |
1、QM2 |
| Week | 包括年份在內的一周 | 完成 | 52 ≤ value ≤ 53 |
2023 年第 50 週、W50-2023、2023-W50 |
| 年的週數 | 一年中的一周 | 部分的 | 52 |
第 50 週,W50,第 50 |
| 季度週 | 本季度的一周 | 部分的 | 13 |
第 10 季第 10 週、QW10、10 |
| 每月的一周 | 每月的一週 | 部分的 | 5 |
月份第 2 週,MW2、2 |
| Date | 日期 | 完成 | 365*Y ≤ value ≤ 366*Y |
12/31/2025 |
| 年份中的日期 | 一年中的一天 | 部分的 | 365 ≤ value ≤366 |
365、D1 |
| 季度中的某天 | 季度的某一天 | 部分的 | 92 |
第 10 季度日,QD2, 50 |
| 月份的日期 | 月份中的某一天 | 部分的 | 31 |
月 30 日,MD10,30 |
| 星期幾 | 星期幾 | 部分的 | 7 |
第 5 週,WD5、5 |
除了這些類別之外,您還可以將表格上任意數量的直欄與「 時間相關 」類別相關聯。 目前在日曆選項中無法做到這一點,但只能使用外部工具或 TMDL 來完成。
備註
在執行計算時,除了和DATEADD之外的所有函數會移除指派給SAMEPERIODLASTYEAR類別的任何欄的上下文。 未在該行事曆中標記的、但屬於定義行事曆的資料表內之欄位的任何上下文均會保留。
備註
建議您只關聯行事曆中您希望用於時間智慧計算的欄位。
主要資料行與相關資料行的對比
每個類別都必須有主要欄位。 每當該資料行或指派給參考行事曆上相同類別的任何相關聯資料行位於內容中,或需要該類別才能執行計算時,Power BI 都會使用主要資料行。 此外,主要資料行也用於排序。 如果主要資料行中的值不允許其如預期般排序,您可以 將主要資料行設定為依另一個資料行排序 ,或使用另一個資料行,並將原始資料行設為相關聯的資料行。 例如,如果資料行包含包含月號和年份 mm-yyyy 的文字資料,格式為 (亦即 01-2024、 02-2024、 等),則無法在多個年份中正確排序,但使用該 yyyy-mm 格式的資料行會:
您可以將零個或多個相關欄位指派給一個類別。
Validation
驗證和測試您的日曆非常重要,這樣您才能確定它滿足您的需求。 Power BI 中提供的驗證包括 即時驗證 和 離線驗證。
備註
儘管出現離線驗證錯誤,您也可以保存日曆,但建議先解決這些錯誤。 必須修正即時驗證失敗才能儲存。
即時驗證
在行事曆上執行的即時驗證包括:
- 唯一的行事曆名稱。 每個行事曆在語意模型中都必須有唯一的名稱。
- 每個日曆的單一關聯。 一欄不能屬於同一行事曆中的多個類別。
- 時期獨特性。 分配的類別應唯一標識該時期。
- 一致的分類。 這可確保這些欄位在各個行事曆中都與相同的類別相關聯。
時期獨特性
應該始終有途徑來唯一確認各指派類別的時間段。
每當您新增 部分類別時,Power BI 都會驗證完整或部分類別的相符組合也已標記在相同的行事曆中。 如果不是這種情況,則會顯示警告。
例如,設定以週為基礎的計算行事曆時,請務必將至少一個主要資料行指派給下列其中一個類別集:
- Week
- 一年中的一周,年份
- 季度週數、季度
- 季度週數、年度中的季度、年度
- 月份中的某一週,月份
- 月的第幾週、年的月份、年份
- 月份的星期、季度的月份、季度
- 月份的一周、季度月份、一年的季度、年份
一致的分類
欄位在不同的日曆中必須具有一致的類別。 您無法將相同的欄指派給不同的類別,例如 年、年度季度,或在不同行事曆中的時間相關類別。
離線驗證
離線驗證在存取資料表資料時可能會很耗時。 因此,它們不會自動執行,與 即時驗證相反。 若要執行驗證,請選取 [驗證資料]:
離線驗證會檢查下列規則,並在行事曆中的任何規則失效時傳回警告:
- 與分類相關聯的欄沒有空白值。
- 高階與低階的分類具有一對多的基數比率。 例如,與「年份」類別相關聯的資料行應該具有一對多基數,其資料行與「月」類別相關聯。
- 與相同層級上的類別相關聯的資料行具有一對一的基數比率。 例如,與「月份」類別相關聯的資料行應該與「年中月份」和「年份」類別的資料行組合具有一對一的對應關係。
- 指派給相同種類的主要資料行和相關聯的資料行具有一對一的基數比率。 例如,指派給 [月份] 類別時,主資料行 [Month] 和相關聯的資料行 [EnglishMonthName] 應該具有一對一對應關係。
使用行事曆
定義行事曆之後,您可以在 時間智慧函數中參考它。 例如,下列量值會根據 ISO-454 行事曆計算 [總數量] 的月至今總值:
Total Quantity MTD ISO-454 = TOTALMTD ( [Total Quantity], 'ISO-454' )
如果未定義行事曆並傳回錯誤:
不過,即使已定義行事曆,量值仍可能傳回錯誤。 如果所使用的函數預期行事曆中存在類別,而行事曆沒有該類別,就會發生這種情況。 例如, TOTALWTD 預期行事曆中會出現特定類別。 如果不是,則會傳回錯誤:
時間智能函數和需求類別
許多 時間智慧函式 需要在函式呼叫中參考的行事曆上包含足夠的類別,以便 Power BI 可以識別唯一的特定時間單位。 換句話說,Power BI 需要能夠從執行計算的層級一直「升級」到個別年份。 例如,在季度上執行計算時,例如使用TOTALQTD指派季度類別,或根據期間唯一性驗證的指示,在行事曆中同時指派年度季度和年份。
情境清除
時間智能函數的運作方式是從某個時間點開始,然後對其執行一些操作,以產生不同的時間點。 當然,初始時間點可能會與此結果衝突,因此會導致篩選內容相交,預設情況下會產生部分或空白結果。 例如,請考慮下列案例。
行事曆定義
我們有一個簡單的公曆,它標記了三個類別,定義為:
| 類別 | 主要欄位 |
|---|---|
| 年 | 年 |
| 一年中的月份 | 年份中的月份 |
| 季度 | 季度 |
量值定義
定義了兩個基本量值:一個用於計算總銷售額,另一個用於計算上一季度的總銷售額:
[TotalSales] = CALCULATE ( SUM( FactInternetSales[SalesAmount] ) )
[LastQuarterSales] = CALCULATE ( [TotalSales], DATEADD( GregorianCalendar, -1, QUARTER ) )
範例:內容清除的運作方式
我們的圖表使用 Year 和 MonthOfYear 欄位,以每月為粒度進行瀏覽:
| 年 | 年份中的月份 | TotalSales | 上季度銷售 |
|---|---|---|---|
| 2011 | 1 | 10 | |
| 2011 | 2 | 20 | |
| 2011 | 3 | 30 | |
| 2011 | 4 | 40 | 10 |
| 2011 | 5 | 50 | 20 |
在此表格中,以粗體顯示的列是以月份層級瀏覽的,針對2011年4月。 因此,此列中的所有量值都會在 [Year] == 2011 和 [MonthOfYear] == 4 的篩選內容下進行評估。
如預期,這裡 的 TotalSales 計算為 2011 年 4 月的總銷售額。
LastQuarterSales 類似地計算 TotalSales,但會提供行事曆型函式所 DATEADD 提供的額外篩選條件。
對於此列, DATEADD 初始起點為 2011 年 4 月,並產生恰好一季前的時間點:2011 年 1 月。 因此,可能會預期此 TotalSales 會在下列兩個篩選內容下計算:
- 由目前資料列的瀏覽欄位提供:
{ [Year] == 2011, [MonthOfYear] == 4 }(相當於 2011 年 4 月) - 由該 DATEADD 過濾器提供:
{ [Year] == 2011, [MonthOfYear] == 1 }(相當於 2011 年 1 月)
顯然,這兩個篩選環境會發生衝突 - 我們無法將當月的總銷售額評估為 2011 年 1 月 和 2011 年 4 月。 這樣的交叉不會產生任何結果。
然而,事實並非如此。 相反地,根據日曆定義,日曆型時間智慧函數會識別哪些類別的欄可能會導致衝突,並根據函數執行的時間操作進行分析。 在此情況下,DATEADD 會在 季度 層級執行轉移。 此函數會識別 [年份] 和 [年份月份 ] 類別可能會因為 [季度] 類別的欄變更而變更。 因此,函式會清除那些類別中所有(主要及相關)的資料行上的篩選環境定義。
換句話說,我們可以說 Year 和 Month of Year 類別是 Quarter 類別的依賴項。 相反,我們可以說季度類別是年份和年份月份類別的依賴項。
背景清除的運作方式
提供此圖表是為了更好地視覺化不同時間類別之間的相依關係。 在此結構中,每個類別代表標記到該類別的所有欄位(主要和相關)。 類別會透過箭頭連線至其相依性。 例如,「Month」依賴於「Year」、「Quarter of Year」、「Month Of Quarter」、「Quarter」和「Month of Year」。
在行事曆中標記的欄或其相關聯的 排序依列 上設定內容時,會清除先前的篩選內容:
- X 的所有類別 相依性 。這可以被認為是 X 以上的所有類別。
- X 及其相依性的所有類別 依賴項 (即,從上面的 1. 開始)。 這可以被認為是 X 以下的所有類別和上面 1 中的所有類別。
備註
上下文清除會發生在行事曆或相關聯排序資料行中標記的資料行上,無論上下文是使用時間智慧函數或其他方式設定的。
時間相關欄位
大多數時間智能函數 ( DATEADD 和 SAMEPERIODLASTYEAR除外) 將清除所有與時間相關的欄和相關排序 欄的上下文。
跨行事曆行為
如果在同一個表格上定義了多個日曆,則會針對表格上定義 的每個 日曆完成這些流程。 這包括有關時間相關欄的上下文清除的備註。 換句話說,假設資料表定義了三個行事曆:Calendar1、Calendar2 和 Calendar3。 如果在 Calendar1 中的類別 “X” 上設定了過濾器上下文,則在所有三個日曆上都會執行上述過程。
範例:篩選器設定為「季度」
如果在類別「季度」上設定篩選內容,則程式如下所示。
行事曆的 TMDL 指令碼
createOrReplace
table Date
lineageTag: xyz
column Date
dataType: dateTime
formatString: Long Date
lineageTag: abc
summarizeBy: none
sourceColumn: Date
column Year
dataType: string
lineageTag: abc
summarizeBy: none
sourceColumn: Year
annotation SummarizationSetBy = Automatic
column Month
dataType: string
lineageTag: def
summarizeBy: none
sourceColumn: Month
annotation SummarizationSetBy = Automatic
column MonthName
dataType: string
lineageTag: ghi
summarizeBy: none
sourceColumn: MonthName
sortByColumn: SortByMonth
changedProperty = SortByColumn
annotation SummarizationSetBy = Automatic
column DutchMonthName
dataType: string
lineageTag: jkl
summarizeBy: none
sourceColumn: DutchMonthName
annotation SummarizationSetBy = Automatic
column 'Holiday Name'
dataType: string
lineageTag: mno
summarizeBy: none
sourceColumn: Holiday Name
annotation SummarizationSetBy = Automatic
column IsWorkingDay
dataType: string
lineageTag: pqr
summarizeBy: none
sourceColumn: IsWorkingDay
annotation SummarizationSetBy = Automatic
...
calendar 'Demo Calendar'
lineageTag: def
calendarColumnGroup = year
primaryColumn: Year
calendarColumnGroup = month
primaryColumn: Month
associatedColumn: DutchMonthName
associatedColumn: MonthName
calendarColumnGroup
column: 'Holiday Name'
column: isWorkingDay
備註
請注意,如果您未在 TMDL 中指定 calendarColumnGroup 任何類別,則資料行會標示為 時間相關。 在此範例中, 「假日名稱 」和 「isWorkingDay 」是 示範行事曆上與時間相關的資料行。
整合起來:時間移動的範例
某些 時間智慧函數 僅橫向移動上下文,考慮所有列,而其他函數則執行分層轉移——根據列是否在日曆中標記來保留或清除上下文。 時間智慧函數可以根據是否允許分層輪換分為兩組:
- 已修復。 該組中的函數是 DATEADD 和 SAMEPERIODLASTYEAR。 這些函式只允許橫向時移,不會傳回不同詳細層級的值。
- 靈活。 此群組包含所有其他時間智能功能。 這些函數確實允許分層時移,並且根據日曆設置可以返回不同詳細級別的結果。
為了顯示這些行為,讓我們逐步解說一個範例,使用由兩個表格、兩個行事曆和五個量值組成的簡單資料模型。
表格和關係
在此範例中,我們有下列簡單的資料模型:
| Table | Columns |
|---|---|
| Date | 年份、IsWorkingDay、日期 |
| Sales | OrderKey、數量、OrderDate |
Sales 和 Date 資料表與 OrderDate 和 Date 相關。
Calendars
我們在 Date 表格中定義了具有以下對應的行事曆:
| 行事曆名稱 | 類別 | 主要欄位 |
|---|---|---|
| 西曆 | 年 | 年 |
| Date | Date | |
| GregorianWithWorkingDay | 年 | 年 |
| Date | Date | |
| 與時間相關的 | 是工作日 |
這兩個行事曆的對等 TMDL 定義為:
ref table Date
calendar 'Gregorian'
lineageTag: xyz
calendarColumnGroup = year
primaryColumn: Year
calendarColumnGroup = date
primaryColumn: Date
calendar 'GregorianWithWorkingDay'
lineageTag: dc4fc383-1661-4112-8afb-930d324fbb6e
calendarColumnGroup = year
primaryColumn: Year
calendarColumnGroup = date
primaryColumn: Date
calendarColumnGroup
column: IsWorkingDay
措施
在 Sales 資料表上,我們定義下列量值:
Total Quantity = SUM ( 'Sales'[Order Quantity] )
OneYearAgoQuantity =
CALCULATE ( [Total Quantity], DATEADD ( 'Gregorian', -1, YEAR ) )
OneYearAgoQuantityTimeRelated =
CALCULATE ( [Total Quantity], DATEADD ( 'GregorianWithWorkingDay', -1, YEAR ) )
FullLastYearQuantity =
CALCULATE ( [Total Quantity], PARALLELPERIOD ( 'Gregorian', -1, YEAR ) )
FullLastYearQuantityTimeRelated =
CALCULATE ( [Total Quantity], PARALLELPERIOD ( 'GregorianWithWorkingDay', -1, YEAR )
)
橫向移位範例
讓我們建立視覺效果,顯示 2024 年和 2025 年的 Year、MonthOfYear、IsWorkingDay、Total Quantity、OneYearAgoQuantity 和 OneYearAgoQuantityTimeRelated:
2025 年的 OneYearAgoQuantity 和 OneYearAgoQuantityTimeRelated 的所有值都符合一年前(2024)的 Total Quantity,且具有相同的 IsWorkingDay 值。
這表示 DATEADD 能維護 [日期] 資料表中包含所使用行事曆的任何欄位的內容,不論該行事曆是否被標記,或是否在該行事曆上標記為與時間相關。 由於在 量值定義 中,我們指示 DATEADD 向後移動一年 ,因此唯一內容移動的資料行是與年份類別相關聯的資料行。 IsWorkingDay 資料行在行事曆中是否被標記為時間相關,或根本沒有被標記,都不會改變結果。 唯一表現出此行為的其他函數是 SAMEPERIODLASTYEAR。
階層位移範例
現在,讓我們看一個例子,其中列是否被標記為與時間相關確實會改變結果。
為此,我們將重新建立與上一個範例相同的視覺效果,但這次我們將使用 FullLastYearQuantity 和 FullLastYearQuantityTimeRelated 量值:
這顯示PARALLELPERIOD會保留行事曆中未標記的資料行的上下文,但會清除那些標記為與時間相關的資料行的上下文。 FullLastYearQuantity 使用 公曆,其中 IsWorkingDay 未在行事曆中標記,而 FullLastYearQuantityTimeRelated 則使用 GregorianWithWorkingDay 行事曆,其中 IsWorkingDay 被標記為時間相關。 除了DATEADD和SAMEPERIODLASTYEAR之外,所有時間智慧功能都以這種方式運作。
獎勵:如果您真的想強制這些函數也保留與時間相關的列的上下文,您可以使用 VALUES:
FullLastYearQuantityTimeRelatedOverride =
CALCULATE ( [Total Quantity], PARALLELPERIOD ( 'GregorianWithWorkingDay', -1, YEAR ), VALUES('Date'[IsWorkingDay]) )
在此情況下, FullLastYearQuantityTimeRelatedOverride 傳回與 FullLastYearQuantity相同的結果。
Conclusion
上面的詳細範例顯示,不同的時間智慧函數的行為會有所不同,具體取決於列是否在行事曆中標記為與時間相關。 DATEADD 並且 SAMEPERIODLASTYEAR 只執行橫向時移。 所有其他 時間智能函數 都允許分層時移。
與日曆搭配使用DATEADD
此DATEADD函數具有特定參數,可以在選取範圍比interval中的DATEADD參數所指示的移位層級更精細時,精確控制如何執行移位。 例如,如果您在日期層級顯示資料,但將參數interval設為 DATEADDMONTH,就會發生這種情況。 例如,在公曆中,將 3 月 3 日至 10 日的期間移動一個月時,將導致 4 月 3 日至 10 日。 然而,由於公曆中的月份長度不同,這可能會導致移動時出現歧義。 以下是基於公曆的範例場景:
從較短的時間轉向較長的時期
例如,從 2 月的選擇開始向前調整一個月,使目標月份為 3 月。
您可以使用參數 extension 來影響班次的執行方式:
| 延伸參數值 | Description | Result |
|---|---|---|
precise |
這會嚴格保留原始日期範圍。 | 2 月 25 日至 28 日移至 3 月 25 日至 28 日。 |
extended |
允許視窗在月底擴展。 | 2 月 25 日至 28 日移至 3 月 25 日至 31 日。 |
從較長的時期轉向較短的時期
例如,若在選擇 3 月的某個項目後向後移動一個月,那麼目標月份將是 2 月。
您可以使用參數 truncation 來影響班次的執行方式:
| 截斷參數值 | Description | Result |
|---|---|---|
anchored |
將結果錨定至較小月份的最後有效日期。 | 3 月 31 日移至 2 月 28 日(或閏年的 29 日)。 |
blank |
當轉移的日期不存在時,傳回 空白。 | 將 3 月 31 日向後移動一個月會返回 空白 (因為 2 月 31 日不存在)。 |
使用行事曆型時間智慧的考量
- 在定義行事曆並受限於 資料列層級安全性(RLS) 規則的事實資料表上執行時間智能計算,可能會導致意料之外的結果。
- 此預覽功能的效能並不代表最終產品。
- 您還無法在 Power BI 服務中撰寫行事曆。
- 您不應該將 自動日期/時間 表與自訂行事曆搭配使用。
- 您無法將行事曆與即時連線或複合模型搭配使用。
- 建議您只關聯行事曆中您希望用於時間智慧計算的欄位。
- 行事曆需要進行 即時 和 離線 驗證。 儘管出現離線驗證錯誤,您也可以保存日曆,但建議先解決這些錯誤。 必須修正即時驗證失敗才能儲存。
- 每個行事曆在資料模型中都必須有唯一的名稱
- 單一表格可以包含多個行事曆
- 包含行事曆的資料表必須少於 200 個直欄。 如果表格包含超過 20,000 列,則無法進行驗證,但您仍然可以新增行事曆。
- 行事曆必須至少將一個主要欄指派給類別
- 行事曆只能將自己表格中的欄指派給類別
- 每個類別都應該有一個主要資料行,而且可以指派零個或多個相關聯的資料行
- DATEADD 有新的參數來控制延伸模組和延伸模組行為,這些參數在 IntelliSense 中無法辨識。
- 任何指定的資料行只能對應至一個類別
- 您無法嵌套使用日曆的時間智慧函式。 例如,不支援下列「DAX 陳述式」:
ThisIsNotSupported = PREVIOUSDAY ( PREVIOUSMONTH( 'Calendar' ) )
相反,您可以執行以下操作:
ThisWorks = CALCULATETABLE ( PREVIOUSDAY ( 'Calendar' ), PREVIOUSMONTH( 'Calendar' ) )
使用內建工具建立日期表
下列範例會使用 Power Query M 或 DAX 建立從 2010 年 1 月 1 日到 2030 年 12 月 31 日的日期資料表。 它包括下列資料行:年份、月號、月名稱、月年、季度、年季度、日和日期。
電源查詢 M
let
StartDate = #date(2010, 1, 1),
EndDate = #date(2030, 12, 31),
NumberOfDays = Duration.Days(EndDate - StartDate) + 1,
DateList = List.Dates(StartDate, NumberOfDays, #duration(1,0,0,0)),
DateTable = Table.FromList(DateList, Splitter.SplitByNothing(), {"Date"}),
AddYear = Table.AddColumn(DateTable, "Year", each Date.Year([Date]), Int64.Type),
AddMonthNumber = Table.AddColumn(AddYear, "Month Number", each Date.Month([Date]), Int64.Type),
AddMonthName = Table.AddColumn(AddMonthNumber, "Month Name", each Date.ToText([Date], "MMMM"), type text),
AddMonthYear = Table.AddColumn(AddMonthName, "Month Year", each Date.ToText([Date], "MMM yyyy"), type text),
AddQuarter = Table.AddColumn(AddMonthYear, "Quarter", each "Q" & Text.From(Date.QuarterOfYear([Date])), type text),
AddYearQuarter = Table.AddColumn(AddQuarter, "Year Quarter", each Text.From(Date.Year([Date])) & " Q" & Text.From(Date.QuarterOfYear([Date])), type text),
AddDay = Table.AddColumn(AddYearQuarter, "Day", each Date.Day([Date]), Int64.Type)
in
AddDay
DAX
DateTable =
ADDCOLUMNS (
CALENDAR ( DATE ( 2010, 1, 1 ), DATE ( 2030, 12, 31 ) ),
"Year", YEAR ( [Date] ),
"Month Number", MONTH ( [Date] ),
"Month Name", FORMAT ( [Date], "MMMM" ),
"Month Year", FORMAT ( [Date], "MMM YYYY" ),
"Quarter", "Q" & FORMAT ( [Date], "Q" ),
"Year Quarter",
FORMAT ( [Date], "YYYY" ) & " Q"
& FORMAT ( [Date], "Q" ),
"Day", DAY ( [Date] ),
"Date", [Date]
)
如需詳細資訊和更多選項,請參閱 日期表格。
相關內容
如需本文的相關資訊,請參閱下列資源:
![顯示示例日期表的前 14 行的屏幕截圖。資料表會定義 Date、Year 和 IsWorkingDay。[日期] 資料行包含日期,[年份] 資料行包含年份值,而 [IsWorkingDay] 資料行是布林值 (True/False) 資料行,指出日期是否為工作天。](media/desktop-time-intelligence/calendars-example-date-table-rows.png)
