search
LoginSignup
0

posted at

updated at

DAX workout - タイム インテリジェンス関数 - FIRSTDATE / LASTDATE

失敗を減らすための仕草
タイム インテリジェンス関数の<dates>パラメータには日付テーブルの日付列を使用する。

Warm up

FIRSTDATE function (DAX)
FIRSTDATE(<dates>)
  • 戻り値は 1列(日付列)のテーブル
  • 戻り値は 2行以上にならない。
  • 戻り値に含まれる値はMINX( Dates, Dates[Date])と同じ。

LASTDATE function (DAX)
LASTDATE(<dates>)
  • 戻り値は 1列(日付列)のテーブル
  • 戻り値は 2行以上にならない
  • 戻り値に含まれる値はMAXX( Dates, Dates[Date])と同じ

Workout-1

DAX クエリ
EVALUATE
FIRSTDATE( Dates[Date] )
Date
2020-01-01

日付テーブルの Date列(日付列)が 2020-01-01 からだから。

DAX クエリ
EVALUATE
LASTDATE( Dates[Date] )
Date
2022-12-31

日付テーブルの Date列(日付列)が 2022-12-31 までだから。

DAX クエリ
EVALUATE
CALCULATETABLE(
	FIRSTDATE( Dates[Date] ),
	YEAR( Dates[Date] ) = 2021,
	MONTH( Dates[Date] ) = 7
)
Date
2021-07-01
DAX クエリ
EVALUATE
CALCULATETABLE(
	LASTDATE( Dates[Date] ),
	YEAR( Dates[Date] ) = 2021,
	MONTH( Dates[Date] ) = 7
)
Date
2021-07-31
DAX クエリ
EVALUATE
CALCULATETABLE(
	FIRSTDATE( Dates[Date] ),
	Dates[Date] = dt"2021-07-15"
)
DAX クエリ
EVALUATE
CALCULATETABLE(
	LASTDATE( Dates[Date] ),
	Dates[Date] = dt"2021-07-15"
)

いずれのクエリも同じ結果(テーブル)を返した。

Date
2021-07-15
DAX クエリ
EVALUATE
{
	ISEMPTY(
		CALCULATETABLE(
			FIRSTDATE( Dates[Date] ),
			YEAR( Dates[Date] ) = 2000
		)
	)
}
DAX クエリ
EVALUATE
{
	ISEMPTY(
		CALCULATETABLE(
			LASTDATE( Dates[Date] ),
			YEAR( Dates[Date] ) = 2000
		)
	)
}

いずれのクエリも同じ結果を返した。

Value
True

日付テーブルに含まれる日付には2000年の日付が含まれていないから。

Workout-2

戻り値がテーブルである。
戻り値がテーブルだからCALCULATE 関数の <filter> パラメータで使用する。

DAX クエリ
EVALUATE
SUMMARIZECOLUMNS(
	Dates[Year],
	"Sales amount FirstDate",
	CALCULATE(
		[Sales amount],
		FIRSTDATE( Dates[Date] )
	)
)

ORDER BY
	Dates[Year]

日付テーブルに含まれる日付の各Dates[Year]ごとでもっとも過去の日付で評価される

DAX クエリ
EVALUATE
SUMMARIZECOLUMNS(
	Dates[Year],
	"Sales amount LastDate",
	CALCULATE(
		[Sales amount],
		LASTDATE( Dates[Date] )
	)
)

ORDER BY
	Dates[Year]

日付テーブルに含まれる日付の各Dates[Year]ごとでもっとも最新の日付で評価される

Workout-3

期待しない結果になる例 : 戻り値をスカラ値として使用する。
EVALUATE
SUMMARIZECOLUMNS(
	Dates[Year],
	"Sales amount",
	VAR _Date = FIRSTDATE( Dates[Date] )	// ❌
//	VAR _Date = LASTDATE( Dates[Date] )		// ❌
	RETURN
	CALCULATE(
		[Sales amount],
		Dates[Date] = _Date					// ❌
	)
)

ORDER BY
	Dates[Year]
よくない例 : 日付テーブル以外の日付時刻列で使う。
EVALUATE
SUMMARIZECOLUMNS(
	Dates[Year],
	"Sales amount",
	CALCULATE(
		[Sales amount],
		FIRSTDATE( Sales[受注日] )			// ❌
	)
)

ORDER BY
	Dates[Year]

Workout-4

MINX / MIN / MAXX / MAX との動作の違いを知る。
SE(Storage engine)で 集計する/集計しない の違いがあるんだぜ。

  • 日付テーブル以外の日付時刻列で FIRSTDATE / LASTDATE 関数を使わない理由
  • 日付テーブルの日付列でも FIRSTDATE / LASTDATE 関数を使わないときもある理由

DAX クエリ
EVALUATE
FIRSTDATE( Dates[Date] )
Import(xmSQL)
SET DC_KIND="AUTO";
SELECT
'Dates'[Date]
FROM 'Dates';
DirectQuery(T-SQL)
SELECT 
TOP (1000001) [t1].[Date]
FROM [Dates] AS [t1]
GROUP BY [t1].[Date] 

DAX クエリ
EVALUATE
{ MIN( Dates[Date] ) }
Import(xmSQL)
-- メタデータから取得
DirectQuery(T-SQL)
SELECT MIN([t1].[Date])
 AS [a0]
FROM [Dates] AS [t1] 

DAX クエリ
EVALUATE
{
	CALCULATE(
		MIN( Dates[Date] ),
		Dates[Date] <= dt"9999-12-31"
	)
}
Import(xmSQL)
SET DC_KIND="AUTO";
SELECT
MIN ( 'Dates'[Date] )
FROM 'Dates'
WHERE
	 ( PFCASTCOALESCE ( 'Dates'[Date] AS  REAL ) <= COALESCE ( 2958465.000000 )  ) ;
DirectQuery(T-SQL)
SELECT MIN([t1].[Date])
 AS [a0]
FROM [Dates] AS [t1]
WHERE 
([t1].[Date] <= CAST( '9999-12-31 00:00:00' AS datetime))

Workout-5

Context transition
FIRSTDATE / LASTDATE (タイム インテリジェンス関数)の <dates> パラメータに日付列を使用するときにはコンテキストトランジションが発生する。CALCULATETABLE( DISTINCT( Dates[Date] ) )

DAX クエリ
EVALUATE
ADDCOLUMNS(
    Dates,
    "LastDate", LASTDATE( Dates[Date] ),
    "MaxDate",
        MAXX(
            Dates,
            Dates[Date]
        ),
    "Calculate_MaxDate",
        CALCULATE(
            MAXX(
                Dates,
                Dates[Date]
            )
        )
)

LastDate 列と MaxDate 列は同じ評価結果にはならない。

思ったこと🙄

同じ結果が得られるからといって、なんでもよいというわけではない。
記述したメジャーが含まれる DAX クエリで最善を探るとよい。
動作について知ることがスタート地点。

その他

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0