Power BI で時間ベースの計算を実装する

Power BI には、自動日付テーブルまたは追加した日付テーブルに依存する、時間ベースの計算を実行するための複数のツールが用意されています。

カレンダーベースのタイム インテリジェンス (プレビュー) を使用することをお勧めします。これは、任意の予定表を満たすのに最適なパフォーマンスと最高の柔軟性を提供するためです。

次の表は、提供されている 3 つのツールを比較したものです。

Tool セットアップ作業が必要 管理の容易さ 柔軟性 注記
自動日付/時刻 ほぼゼロ つらい 低い 複数の非表示の日付テーブルが作成されるため、モデル サイズが大きくなります
クラシック タイム インテリジェンス 中間 易しい 低い 日付テーブルを作成する必要があります。グレゴリオ暦またはシフトグレゴリオ暦を想定し、一部の特定のシナリオでパフォーマンスの問題に苦しんでいます
カレンダー ベースのタイム インテリジェンス 高い 中間 高い 日付テーブルを作成することをお勧めします。これは最高の柔軟性とパフォーマンスを提供しますが、セットアップコストが増加します。

注

代替のタイムインテリジェンス手法、特に特定のユースケースを除き、オフセットを計算するために日付テーブルに列を追加する手法の使用はお勧めしません。 これらのアプローチは、単純な DAX 数式のために初心者にアピールできるかもしれませんが、セマンティック モデルが不必要に膨らむ傾向があります。 この肥大化により、データの更新が遅くなり、データセットの増加に応じてレポートのパフォーマンスが低下する可能性があります。

自動日付/時刻

自動日付/時刻機能では、データ モデルの各日付フィールドに対して非表示の日付テーブルが自動的に作成されます。 この自動動作の詳細については、「 Power BI Desktop で自動日付/時刻を適用する」を参照してください。

注

自動日付/時刻は単純なモデルに便利なオプションですが、より複雑なシナリオや大規模なモデルでは推奨されません。 これらのモデルでは、柔軟性を高めるために専用のテーブルを作成することをお勧めします。

日付テーブルを追加する

ほとんどのモデルでは、日付テーブル (または一部のシナリオではそれ以上) を追加することをお勧めします。 多くのデータ アナリストは、独自の日付テーブルを作成することを好みます。これは問題ありません。

このようなテーブルを作成するには、次のような複数の方法があります。

最適なオプションは、さまざまな要因に依存し、このチュートリアルの範囲を超えています。

時間を基にした計算を取り扱う

自動日付/時刻を使用していない場合、Power BI でタイム インテリジェンス関数を使用して時間ベースの計算を実行する別の方法が 2 つあります。

注

特定のシナリオでは、 テーブルを日付テーブルとして設定 する必要があります。

クラシック タイム インテリジェンス

このオプションでは、モデルに日付テーブルを含め、 それに応じて設定する必要があります。 その後、 タイム インテリジェンス関数 を使用し、日付テーブルを参照できます。 たとえば、Date 列を含む日付テーブルとして設定する日付テーブルが モデル内に 存在する場合は、次を使用できます。

SAMEPERIODLASTYEAR ( 'Date'[Date] )

これは高速で簡単なアプローチですが、 カレンダーベースのアプローチに比べて多くの欠点があります。

  • 日付テーブルを設定する必要がある
  • これは、少なくとも 1 つの専用の日付テーブルを持つモデルでのみ機能します
  • 使用される日付列には、最初の日付と最後の日付の間に不足している日付は含まれていない必要があります。 最初の日付と最後の日付の間に不足している日付がある場合は、エラーが発生します。
  • グレゴリオ暦またはシフトグレゴリオ暦 (7 月 1 日から始まるがグレゴリオ暦に従う会計年度など) 用に最適化されているため、柔軟性が低くなります。
  • 週ベースの計算は提供されません
  • 特定のシナリオでは、時間ベースの計算はうまく機能しません。

注

拡張されたカレンダー ベースのアプローチを使用することをお勧めします。

予定表ベースのタイム インテリジェンス (プレビュー)

カレンダーは、テーブルに追加されるメタデータ定義であり、そのテーブルのどの列がどの時刻の属性を表しているのかを示します。 モデル内の任意のテーブルに 1 つ以上のカレンダーを定義できます。 モデルでカレンダーを定義したら、タイム インテリジェンス関数でカレンダーを参照できます。 たとえば、定義された会計カレンダーを使用して売上の合計年累計を計算する方法を次に 示します。

TOTALYTD ( [Sales], 'Fiscal Calendar' )

カレンダーベースのタイム インテリジェンスの利点

カレンダー ベースのタイム インテリジェンスの主な利点は次のとおりです。

任意の予定表で動作します

カレンダーを使用すると、年、四半期、月、週で時間を分割する方法を柔軟に決定できます。 たとえば、次のパターンに従うカレンダーを定義できます。

  • Gregorian
  • シフトグレゴリオ暦
  • 小売 (445、454、544 パターン)
  • 13 か月
  • 月

予定表の構造に関する Power BI の組み込みの想定がないため、可能性は無限大です。 カレンダー ベースのタイム インテリジェンスでは、基になる日付に関する前提条件はありません。 すべての計算では、基になるデータが正確に as-is使用されます。

希薄な日付

クラシック タイム インテリジェンス では、指定された日付列が完了している必要があります。最初の日付と最後の日付の間に日付が見つからない場合は、エラーがスローされます。 カレンダー ベースのタイム インテリジェンス関数には、このような要件はありません。 その代わりに、そのままの日付で動作します。 完全な専用の予定表テーブルを用意することをお勧めしますが、その必要はなくなりました。 たとえば、すべての小売店が週末に閉じている場合、売上がないため週末の日をスキップすることができます。 週末が土曜日と日曜日の場合は、これで週末のデータがないテーブルを基にしたカレンダーで PREVIOUSDAY を使用して、月曜日から直接金曜日に移動できるようになりました。

週ベースの計算

カレンダー ベースのタイム インテリジェンスは、1 週間単位で動作する DAX 関数を直接提供します。 たとえば、週から日までの合計は、 TOTALWTDを使用して直接計算できます。

TOTALWTD ( Expr, CalendarName )

パフォーマンスの向上

一部のシナリオでは、カレンダーベースのタイム インテリジェンス関数を従来のタイム インテリジェンス関数と比較すると、パフォーマンスが向上することがあります。 たとえば、週ごとにグループ化され、 TOTALYTD ( ..., CalendarName ) を使用して年累計の計算を実行するビジュアルは、通常、対応する従来の TOTALYTD ( ..., TableName[DateColumnName] )が使用された場合よりも迅速に実行する必要があります。 これが発生する可能性がある理由の詳細については、「 コンテキストクリア 」セクションを参照してください。

拡張 DAX タイム インテリジェンス プレビューを有効にする

まず、 拡張 DAX タイム インテリジェンス プレビュー機能を有効にする必要があります。

  1. Power BI Desktop で、[ファイル > オプションと設定] > [オプション] > プレビュー機能に移動します。
  2. 拡張 DAX タイム インテリジェンス プレビューを選択します。
  3. OK を選択
  4. Power BI Desktop を再起動する

予定表を管理する

予定表を管理するには、予定表を含む、または予定表を定義するテーブルを右クリックし、テーブルを選択した後、[テーブル ツール] リボンの [予定表] オプションを選択します。

テーブルの予定表オプションを開くエントリ ポイントを示すスクリーンショット。

または、外部ツールまたは TMDL ビュー を使用してカレンダーを定義することもできます。 詳細については、 TMDL スクリプトを参照してください。

カレンダーは、定義されているテーブルの下の モデル エクスプローラー にも表示されます。

セマンティック モデルのモデル エクスプローラーを示すスクリーンショット。[日付] テーブル ノードが展開され、予定表が強調表示されます。

予定表のオプション画面

予定表オプション画面には、選択したテーブルで定義されている予定表が表示されます。 ここでは次を実行できます。

  • [新しい予定表] を選択して新しい予定表を作成する
  • [編集] を選択して既存の予定表を編集する
  • [削除] を選択して既存の予定表を削除する
  • [日付テーブルとしてマーク] を選択して、テーブルを日付テーブルとして設定する

テーブルの予定表オプションを示すスクリーンショット。

列カテゴリの割り当て

カレンダーを定義するには、名前を付け、列をカテゴリに割り当てる必要があります。 各カテゴリは時間単位を表し、特定の 列カテゴリ を使用できます。 予定表を保存するには、少なくとも 1 つのプライマリ列をカテゴリに割り当てる必要があります。 各カテゴリには プライマリ列が必要であり、0 個以上の列を関連付けることができます。 カテゴリに関連付けられている列がコンテキスト内にある場合は常に、Power BI で表示される時間の単位が認識されます。 さらに、 TOTALMTD Power BI などの一部の関数では、参照される予定表の関連カテゴリにマップされたプライマリ列を使用して、要求された計算を実行します。 カテゴリに列を割り当てるには、[カテゴリの追加] メニューから カテゴリ を選択し、関連付けられているプライマリ列とオプションの列を選択します。

予定表の作成と編集画面を示すスクリーンショット。

使用可能な列のカテゴリ

次の表に、使用可能なカテゴリを示します。 この表には、グレゴリオ暦の値とカーディナリティの例も示されています。

カテゴリは、次の 2 つのグループに分かれています。

  • 完了。 [完了]カテゴリに割り当てられた列のデータは、時間の期間を一意に識別するのに充分です。
  • 部分。 部分カテゴリに割り当てられた列のデータでは、期間を一意に識別するには不十分です。
カテゴリ Description タイプ グレゴリオ暦のカーディナリティの例 グレゴリオ暦の列値の例
年 年 完成 Y = 年数 2024, 2025
Quarter 年を含む四半期 完成 4*Y 2024 年第 1 四半期、2025 年第 2 四半期
年の四半期 年度の四半期 Partial 4 第1四半期、YQ1、Q1、第2四半期
月 年を含めた月 完成 12*Y ≤ value ≤ 13*Y 2023 年 1 月、2024 年 2 月
年の月 一年の月 Partial 12 1月、年月11、YM11、M11、11
四半期の月 四半期の月 Partial 3 1、QM2
Week 年が含まれる週 完成 52 ≤ value ≤ 53 第 50 週 2023、W50-2023、2023-W50
年の週 年間の週 Partial 52 週 50、W50、50
四半期の週 四半期の週 Partial 13 第10週、QW10、10
月の週 月の1週間 Partial 5 2週目の月、MW2、2
日付 日付 完成 365*Y ≤ value ≤ 366*Y 2025/12/31
年の日 その年の一日 Partial 365 ≤ value ≤366 365、D1
四半期の特定の日 四半期の日 Partial 92 10番目のクォーターデー、QD2、50
月の日 月の日 Partial 31 月日30日, MD10, 30
曜日 週の曜日 Partial 7 週 5 日、WD5、5

これらのカテゴリに加えて、テーブル上の任意の数の列を 時間関連の カテゴリに関連付けることができます。 これは現在、予定表のオプションでは使用できませんが、代わりに外部ツールまたは TMDL を使用してのみ実行できます。

注

時間関連のカテゴリに割り当てられている列のコンテキストは、DATEADDとSAMEPERIODLASTYEARを除くすべての関数で計算を実行するときに削除されます。 予定表が定義されているが、その予定表でタグ付けされていないテーブルの一部である列に関するコンテキストは保持されます。

注

タイム インテリジェンス計算で使用する予定表の列のみを関連付けすることをお勧めします。

プライマリ列と関連列

カテゴリごとにプライマリ列が必要です。 参照先の予定表の同じカテゴリに割り当てられている列または関連付けられている列がコンテキスト内にあるか、計算を実行するためにカテゴリが必要な場合、Power BI ではプライマリ列が使用されます。 さらに、プライマリ列は並べ替えに使用されます。 プライマリ列の値で想定どおりに並べ替えができない場合は、 プライマリ列を別の列で並べ替えるように構成 するか、別の列を使用して元の列を関連付けられた列にすることができます。 たとえば、 mm-yyyy 形式の月番号と年を含むテキスト データを含む列 (つまり、 01-2024、 02-2024など) は、複数年にわたって正しく並べ替えられませんが、 yyyy-mm 形式を使用する列は次のようになります。

2 つのテーブルを示すスクリーンショット。各テーブルには 1 つの列があります。最初のテーブルには、月番号と年のテキスト情報を mm-yyyy 形式で含む列が含まれており、2 番目のテーブルには同じ情報が yyyy-mm 形式で含まれています。mm-yyyy 形式のデータを含む列が正しく並べ替えられません。

1 つのカテゴリに 0 個以上の関連付けられた列を割り当てることができます。

Validation

予定表がニーズを満たしていることを確認できるように、予定表を検証してテストすることが重要です。 Power BI で提供される検証には、 リアルタイム検証 と オフライン検証の両方が含まれます。

注

オフライン検証エラーがあっても予定表を保存できますが、最初に解決することをお勧めします。 保存するには、リアルタイム検証エラーを修正する必要があります。

リアルタイム検証

予定表で実行されるリアルタイム検証は次のとおりです。

  • 一意の予定表名。 各カレンダーは、セマンティック モデル内で一意の名前を持つ必要があります。
  • カレンダーごとに1件の関連付け。 1 つの列が同じ予定表内の複数のカテゴリに属することはできません。
  • 期間の一意性。 割り当てられたカテゴリは、期間を一意に識別する必要があります。
  • 一貫性のある分類。 これにより、列が予定表全体で同じカテゴリに関連付けられます。

期間の一意性

割り当てられたカテゴリの期間を一意に識別するためのパスが常に存在する必要があります。

部分的なカテゴリを追加するたびに、Power BI は、完全または部分的なカテゴリの一致する組み合わせも同じ予定表にタグ付けされていることを検証します。 そうでない場合は、警告が表示されます。

リアルタイム検証エラーが表示されたカレンダーの作成と編集画面を示すスクリーンショット。

たとえば、週単位の計算用にカレンダーを設定する場合は、少なくともプライマリ列を次のいずれかのカテゴリ セットに割り当てるようにします。

  • Week
  • 年の第何週、年
  • 四半期の週、四半期
  • 四半期の週、年の四半期、年
  • 今月の週番号、月
  • 月の週、年の月、年
  • 月内の週、四半期内の月、四半期
  • 月の週、四半期の月、年の四半期、年

一貫性のある分類

列には、カレンダーを通じて統一されたカテゴリが必要です。 年、四半期、時間関連などの異なるカテゴリに同じ列を別のカレンダーで割り当てることはできません。

オフライン検証

オフライン検証は、テーブル データにアクセスする際に時間がかかる可能性があります。 そのため、 リアルタイムの検証とは対照的に、自動的には実行されません。 検証を実行するには、[データの 検証] を選択します。

予定表の作成と編集画面を示すスクリーンショット。[データの検証] ボタンが強調表示されています。

オフライン検証では、次の規則がチェックされ、予定表でルールが無効になっている場合は警告が返されます。

  • カテゴリに関連付けられている列に空白の値がありません。
  • 上位レベルと下位レベルのカテゴリでは、一対多カーディナリティの比率があります。 たとえば、Year カテゴリに関連付けられている列は、Month カテゴリに関連付けられた列と一対多のカーディナリティを持つ必要があります。
  • 同じレベルのカテゴリに関連付けられている列には、1 対 1 のカーディナリティ比があります。 たとえば、月カテゴリに関連付けられている列は、年の月および年カテゴリに関連付けられている列の組み合わせと1対1のカーディナリティを持つ必要があります。
  • 同じカテゴリに割り当てられたプライマリ列と関連付けられた列のカーディナリティ比率は 1 対 1 です。 たとえば、Month カテゴリに割り当てられている場合、プライマリ列 Month と関連する列 EnglishMonthName は 1 対 1 のカーディナリティを持つ必要があります。

暦の操作

カレンダーが定義されたら、 タイム インテリジェンス関数で参照できます。 たとえば、次のメジャーは、ISO-454カレンダーに対して合計数量の月次累計値を計算します。

Total Quantity MTD ISO-454 = TOTALMTD ( [Total Quantity], 'ISO-454' )

カレンダーが定義されておらず、エラーが返される場合:

TOTALMTD関数でカレンダーパラメーターを使用するメジャーが、存在しないカレンダーに対して示されるスクリーンショット。

ただし、カレンダーが定義されていても、指標がエラーを返す可能性があります。 これは、使用される関数が予定表にカテゴリが存在することを想定していて、予定表にそのカテゴリがない場合に発生します。 たとえば、 TOTALWTD は、予定表に特定のカテゴリが存在することを想定しています。 そうでない場合は、エラーが返されます。

TOTALWTD関数を使用したメジャーと、必要なカテゴリを定義していない有効なカレンダー参照を示すスクリーンショット。

タイム インテリジェンス関数と必要なカテゴリ

多くの タイム インテリジェンス関数では、 Power BI が一意の特定の時間単位を識別できるように、関数呼び出しで参照される予定表に十分なカテゴリを含める必要があります。 言い換えると、Power BI は、計算が実行されるレベルから個々の年まで "ウォークアップ" できる必要があります。 たとえば、四半期に対して計算を実行する場合は、たとえば、 TOTALQTD を使用して 四半期 カテゴリを割り当てるか、カレンダー の [年の四半期 ] と [ 年 ] の両方を、 期間の一意性 の検証に従って割り当てます。

注

一部の関数の名前は、計算が動作するレベル ( TOTALYTD など) を示し、他の関数の場合はパラメーターとコンテキスト ( DATEADD など) に依存します。

コンテキストをリセットする

タイム インテリジェンス関数は、ある時点から開始し、別の時点を生成するためにそれに対して何らかの操作を実行することによって動作します。 当然ながら、初期の時点がこの結果と競合する可能性があるため、既定では部分的または空の結果が生成されるフィルター コンテキストの交差が発生します。 たとえば、次のシナリオを考えてみましょう。

予定表の定義

次のように定義された 3 つのカテゴリにタグを付け、シンプルなグレゴリオ暦を使用しています。

カテゴリ プライマリ列
年 年
年の月 MonthOfYear
Quarter Quarter

測定定義

2つの基本的なメジャーが定義されています。1つは売上合計を計算し、もう1つは前四半期の売上合計を計算するためのものです。

[TotalSales] = CALCULATE ( SUM( FactInternetSales[SalesAmount] ) )
[LastQuarterSales] = CALCULATE ( [TotalSales], DATEADD( GregorianCalendar, -1, QUARTER ) )

例: コンテキストクリアのしくみ

次の表のビジュアルでは、 Year 列と MonthOfYear 列を使用して、月単位で参照します。

年 MonthOfYear 総売上 前四半期売上
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 月という 4 分の 1 前の時点になります。 その結果、次の 2 つのフィルター コンテキストでこの TotalSales が計算される可能性があります。

  • 現在の行の参照列によって提供されます: { [Year] == 2011, [MonthOfYear] == 4 } (同等、2011 年 4 月)
  • DATEADD フィルターによって提供されます: { [Year] == 2011, [MonthOfYear] == 1 } (同等、2011 年 1 月)

明らかに、これら 2 つのフィルター コンテキストは競合します。2011 年 1 月 と 2011 年 4 月の両方として、当月の売上合計を評価することはできません。 このような交差では結果が得られません。 ただし、これは発生しません。 代わりに、カレンダー定義に基づいて、カレンダーベースのタイム インテリジェンス関数は、関数が実行する時間操作に従って、競合が発生する可能性があるカテゴリの列を識別します。 この場合、 DATEADD は 四半期 レベルでシフトを実行します。 この関数は、四半期カテゴリの列が変更された結果、Year と Month of Year の両方のカテゴリが変更される可能性があることを識別します。 したがって、この関数は、これらのカテゴリにタグ付け されているすべての (プライマリ列と関連付けられた列の両方) のフィルター コンテキストをクリアします。

言い換えると、 Year と Month of Year カテゴリは Quarter カテゴリの依存関係であると言えます。 逆に、 四半期 カテゴリは 年 と 月の カテゴリに依存していると言えます。

コンテキストのクリアのしくみ

すべてのカレンダー カテゴリの格子構造図。

この図は、さまざまな時間カテゴリ間の依存関係をより適切に視覚化するために提供されています。 この格子の各カテゴリは、そのカテゴリにタグ付けされたすべての列 (プライマリおよび関連) を表します。 カテゴリは、矢印を使用して依存関係に接続されます。 たとえば、"Month" は "Year"、"Quarter of Year"、"Month Of Quarter"、"Quarter"、"Month of Year" に依存します。

カレンダーでタグ付けされた列または関連する 並べ替え列 にコンテキストが設定されている場合、以前のフィルター コンテキストは次の条件でクリアされます。

  1. X のすべてのカテゴリの 依存関係 。これは、X より上のすべてのカテゴリと考えることができます。
  2. X とその依存関係のそれぞれに関連するすべてのカテゴリ依存関係(つまり、上記の 1 から)。 これは、X の下のすべてのカテゴリと、上記の 1 のすべてのカテゴリと考えることができます。

注

コンテキストのクリアは、タイム インテリジェンス関数を使用してコンテキストが設定されているかどうかに関係なく、カレンダーでタグ付けされた列または関連する 並べ替え列 で行われます。

ほとんどのタイム インテリジェンス関数は、 DATEADD と SAMEPERIODLASTYEARを除き、時間関連のすべての列と関連する 並べ替え列のコンテキストをクリアします。

予定表間の動作

同じテーブルに複数のカレンダーが定義されている場合、これらのプロセスは、テーブルに定義 されているすべての カレンダーに対して完了します。 これには、時間関連列のコンテキストクリアに関する注釈が含まれます。 つまり、テーブルで Calendar1、Calendar2、Calendar3 の 3 つのカレンダーが定義されているとします。 Calendar1 のカテゴリ "X" にフィルター コンテキストが設定されている場合、上記のプロセスは 3 つのカレンダーすべてに対して実行されます。

例: "Quarter" に設定されたフィルター

フィルター コンテキストがカテゴリ "Quarter" に設定されている場合、プロセスは次のようになります。

  1. まず、"Quarter" カテゴリのすべての依存関係が考慮されます。

    カテゴリ Quarter: Dependencies から始まるフィルター コンテキストクリア動作の例。

  2. 次に、"Quarter" とその依存関係全てが考慮されます。

    カテゴリ Quarter: Dependents から始まるフィルター コンテキストクリア動作の例。

  3. 最後に、最終的な結果は次のようになります。 すべての赤い色のカテゴリでは、以前のフィルター コンテキストが削除され、新しいコンテキストが四半期に設定されます。

    カテゴリ四半期から始まるフィルター コンテキストクリア動作の例: 結果

予定表の 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 は デモ カレンダーの時刻に関連する列です。

すべてをまとめる:時間シフトの例

タイム インテリジェンス関数の中には、すべての列を考慮してコンテキストを横方向にのみシフトするものもあれば、カレンダーで列がタグ付けされているかどうかに基づいてコンテキストを保持またはクリアする階層シフトを実行する場合があります。 タイム インテリジェンス関数は、階層シフトを許可するかどうかに基づいて、次の 2 つのグループに分割できます。

  • 修正済み。 このグループの関数は DATEADD と SAMEPERIODLASTYEAR です。 これらの関数は、横方向の時間シフトのみを許可し、別の詳細レベルからの値を返しません。
  • 柔軟性があります。 このグループには、他のすべてのタイム インテリジェンス関数が含まれています。 これらの関数を使用すると、階層的な時間シフトが可能になり、カレンダーの設定に応じて、異なる詳細レベルの結果を返すことができます。

これらの動作を示すために、2 つのテーブル、2 つのカレンダー、5 つのメジャーで構成される単純なデータ モデルを使用した例を見てみましょう。

テーブルとリレーションシップ

この例では、次の単純なデータ モデルがあります。

表 列
日付 年、営業日、日付
Sales 注文キー (OrderKey)、数量 (Quantity)、注文日 (OrderDate)

Date テーブルの行の例を次に示します。 Date テーブルの 例の最初の 14 行を示すスクリーンショット。このテーブルでは、Date、Year、IsWorkingDay が定義されています。[日付] 列には日付、Year 列には年の値、IsWorkingDay 列は、日付が稼働日かどうかを示すブール値 (True/False) 列です。

Sales テーブルの行の例を次に示します。 Sales テーブルの 例の最初の 9 行を示すスクリーンショット。このテーブルでは、OrderKey、OrderDate、および Order Quantity が定義されています。OrderKey 列には各販売注文の一意の番号が含まれています。OrderDate は売上を日付に関連付ける日付で、注文数量は各注文の製品数を表す数値列です。

Sales テーブルと Date テーブルは、OrderDate と Date に関連しています。

サンプル モデルのモデル ビューを示すスクリーンショット。Sales テーブルと Date テーブルと、OrderDate と Date の間の一対多リレーションシップが表示されます。

Calendars

日付テーブルでは、次のマッピングを使用してカレンダーを定義しました。

カレンダー名 カテゴリ プライマリ列
グレゴリオ暦 年 年
日付 日付
グレゴリアン・ウィズ・ワーキング・デイ 年 年
日付 日付
時間関連 IsWorkingDay

これら 2 つのカレンダーの同等の 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 を示すビジュアルを作成しましょう。

Year、IsWorkingDay、Total Quantity、OneYearAgoQuantity、OneYearAgoQuantityTimeRelated を示すテーブル ビジュアルを示すスクリーンショット。2025 の OneYearAgoQuantity と OneYearAgoQuantityTimeRelated の値は、同じ IsWorkingDay 値の 2024 の値と一致します。

2025 の OneYearAgoQuantity と OneYearAgoQuantityTimeRelated のすべての値は、同じ IsWorkingDay 値の 1 年前 (2024 年) の合計数量と一致します。

これは、 DATEADD が、タグ付けされていないか、そのカレンダーで時間関連としてタグ付けされているかに関係なく、使用されるカレンダーを含む Date テーブル上の任意の列のコンテキストを維持することを示しています。 メジャー定義では、DATEADDに 1 年だけ戻すように指示したので、コンテキストがシフトされた列は Year カテゴリに関連付けられた列のみでした。 IsWorkingDay 列がカレンダーで時間関連としてタグ付けされているか、まったくタグ付けされていないかにかかわらず、結果は変更されませんでした。 この動作を示す他の関数は、 SAMEPERIODLASTYEARだけです。

階層シフトの例

次に、列に時間関連のタグが付けられているかどうかによって結果が実際に変更される例を見てみましょう。

このためには、前の例と同じビジュアルを再作成しますが、今回は「FullLastYearQuantity」測定値と「FullLastYearQuantityTimeRelated」測定値を使用します。「Year」、「IsWorkingDay」、「Total Quantity」、「FullLastYearQuantity」、「FullLastYearQuantityTimeRelated」を示すテーブルビジュアルのスクリーンショットを表示します。「FullLastYearQuantity」の2025年の値は、同じ「IsWorkingDay」値での2024年の値と一致しますが、「FullLastYearQuantityTimeRelated」の値は、「IsWorkingDay」の値にかかわらず合計数量値と等しくなります。

これは、 PARALLELPERIOD カレンダーでタグ付けされていない列のコンテキストを保持し、時間関連としてタグ付けされた列のコンテキストをクリアすることを示しています。 FullLastYearQuantity では、IsWorkingDay がカレンダーでタグ付けされていない グレゴリオ暦 が使用されましたが、 FullLastYearQuantityTimeRelated では 、IsWorkingDay が時間関連としてタグ付けされた グレゴリオ暦WithWorkingDay カレンダーが使用されていました。 DATEADDとSAMEPERIODLASTYEARを除くすべてのタイム インテリジェンス関数は、このように動作します。

ボーナス: 時間関連の列のコンテキストも保持するようにこれらの関数を強制したい場合は、 VALUESを使用できます。

FullLastYearQuantityTimeRelatedOverride =
CALCULATE ( [Total Quantity], PARALLELPERIOD ( 'GregorianWithWorkingDay', -1, YEAR ), VALUES('Date'[IsWorkingDay]) )

この場合、 FullLastYearQuantityTimeRelatedOverride は FullLastYearQuantityと同じ結果を返します。

Conclusion

上記の詳細な例は、列がカレンダーで時間関連としてタグ付けされているかどうかによって、異なるタイム インテリジェンス関数の動作が異なっていることを示しています。 DATEADD と SAMEPERIODLASTYEAR は、横方向の時間シフトのみを実行します。 他のすべての タイム インテリジェンス関数 では、階層的な時間シフトが可能です。

予定表で DATEADD と DATESINPERIOD を使用する

DATEADD関数と DATESINPERIOD 関数には、interval パラメーターで示されるシフト レベルよりも細かいレベルで選択した場合のシフトの実行方法をきめ細かく制御できる特定のパラメーターがあります。 これは、たとえば、日付レベルのデータを表示しているが、 interval パラメーターをこれらの関数に MONTH に設定している場合に発生します。 たとえば、グレゴリオ暦では、3 月 3 日から 10 日までの期間を月単位でシフトすると、4 月 3 日から 10 日になります。 ただし、グレゴリオ暦の月の長さは異なるため、シフト時にあいまいさが生じる可能性があります。 グレゴリオ暦に基づくシナリオの例を次に示します。

短い期間から長い期間にシフトする

たとえば、2 月の選択で 1 か月先にシフトするので、ターゲットの月は 3 月です。 extensionで DATEADD パラメーターを使用して、シフトの実行方法に影響を与えることができます。

拡張パラメーター値 Description 結果
precise これにより、元の日付範囲が厳密に保持されます。 2 月 25 日から 28 日は、3 月 25 日から 28 日に移行されます。
extended ウィンドウを月末まで拡大できるようにします。 2 月 25 日から 28 日は、3 月 25 日から 31 日に移行されます。
endaligned 選択が月の終わりに達したときに、終了日を宛先月の終わりに合わせます。それ以外の場合は、相対位置が保持されます。 2 月 28 日は 3 月 31 日に、2 月 27 日は 3 月 27 日にシフトされます。

注

DATESINPERIOD には、endbehaviorオプションとpreciseオプションを提供するendaligned パラメーターが用意されています。

より長い期間から短い期間にシフトする

たとえば、3 月の選択で 1 か月後にシフトするので、ターゲットの月は 2 月です。

truncationで DATEADD パラメーターを使用して、シフトの実行方法に影響を与えることができます。

切り捨てパラメーター値 Description 結果
anchored 結果を、小さい月の最後の有効な日付に固定します。 3 月 31 日は 2 月 28 日 (閏年では 29) にシフトされます。
blank シフトされた日付が存在しない場合は、空白を返 します。 3 月 31 日を 1 か月前にシフトすると 、空白 が返されます (2 月 31 日は存在しないため)。

注

このパラメーターは、DATEINPERIOD では使用できません。

予定表ベースのタイム インテリジェンスの操作に関する考慮事項

  • カレンダーを定義し、 行レベル セキュリティ (RLS) ルールの対象となるファクト テーブルに対してタイム インテリジェンス計算を実行すると、予期しない結果が発生する可能性があります。
  • このプレビュー機能のパフォーマンスは、最終製品の代表ではありません。
  • Power BI サービスで予定表を作成することはできません。
  • カスタム カレンダーでは 、自動日付/時刻 テーブルを使用しないでください。
  • ライブ接続モデルまたは複合モデルで予定表を使用することはできません。
  • タイム インテリジェンス計算で使用する予定表の列のみを関連付けすることをお勧めします。
  • 予定表には、 リアルタイム 検証と オフライン 検証の両方が適用されます。 オフライン検証エラーがあっても予定表を保存できますが、最初に解決することをお勧めします。 保存するには、リアルタイム検証エラーを修正する必要があります。
  • 各カレンダーには、データ モデル内で一意の名前が必要です
  • 1 つのテーブルに複数の予定表を含めることができます
  • 予定表を含むテーブルの列数が 200 未満である必要があります。 テーブルに 20,000 行を超える行が含まれている場合、検証は使用できませんが、予定表を追加することはできます。
  • 予定表では、少なくとも 1 つのプライマリ列をカテゴリに割り当てる必要があります
  • 予定表では、独自のテーブルの列のみをカテゴリに割り当てることができます
  • 各カテゴリにはプライマリ列が必要であり、0 個以上の関連付けられた列を割り当てることができます
  • DATEADDには、拡張機能およびその動作を制御するための新しいパラメーターがありますが、IntelliSense では認識されません。
  • 特定の列を 1 つのカテゴリにのみマップできます
  • カレンダーを使用するタイム インテリジェンス関数を入れ子にすることはできません。 たとえば、次の DAX ステートメントはサポートされていません。
ThisIsNotSupported = PREVIOUSDAY ( PREVIOUSMONTH( 'Calendar' ) )

代わりに、次の操作を実行できます。

ThisWorks = CALCULATETABLE ( PREVIOUSDAY ( 'Calendar' ), PREVIOUSMONTH( 'Calendar' ) )

組み込みツールを使用して日付テーブルを作成する

次の例では、Power Query M または DAX を使用して、2010 年 1 月 1 日から 2030 年 12 月 31 日までの日付テーブルを作成します。 年、月番号、月名、年月、四半期、年度四半期、日、日付の各列が含まれます。

Power Query 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]
)

詳細および他のオプションについては、 日付テーブルを参照してください。

この記事に関連する詳細については、次のリソースを参照してください。