在DAX中实现类似SQL窗口函数的首次日期计算及统计需求
DAX度量值:统计满足双条件的非空Name去重计数(大表适配)
需求说明
针对条目量超100万的表,创建DAX度量值,统计非空Name的DISTINCTCOUNTNOTBLANK结果,需同时满足:
- 该Name对应的所有记录中,最小Date大于
20240101 - 该Name存在Date等于
20240601的记录
输入输出示例
输入表(简化版)
| Name | Date |
|---|---|
| Alice | 20240201 |
| Alice | 20240601 |
| Bob | 20231201 |
| Bob | 20240601 |
| Carol | 20240301 |
| Dave | 20240601 |
| Dave | 20240102 |
| (null) | 20240601 |
输出结果
2(仅Alice和Dave符合条件:Bob的最小Date为20231201不满足;Carol无20240601记录;空Name不计入)
SQL实现参考
SELECT COUNT(DISTINCT Name) AS ValidNameCount FROM ( SELECT Name, MIN(Date) OVER (PARTITION BY Name) AS MinDate, Date FROM YourTable WHERE Name IS NOT NULL ) t WHERE MinDate > 20240101 AND Date = 20240601;
常见错误DAX(逻辑顺序颠倒)
Valid Name Count = CALCULATE( DISTINCTCOUNTNOTBLANK('Table'[Name]), 'Table'[Date] = 20240601, CALCULATE(MIN('Table'[Date]), ALLEXCEPT('Table', 'Table'[Name])) > 20240101 )
问题:内层CALCULATE会被外层的Date = 20240601筛选限制,计算的是该Name在20240601当天的最小Date,而非该Name所有记录的全局最小Date,导致逻辑错误。
修正后的DAX度量值
方法1:SUMMARIZE预聚合(大表性能优先)
Valid Name Count = VAR NameAgg = SUMMARIZE( 'Table', 'Table'[Name], "@GlobalMinDate", MIN('Table'[Date]), "@HasJune1Record", ISEMPTY(FILTER('Table', 'Table'[Date] = 20240601)) = FALSE() ) VAR ValidNames = FILTER( NameAgg, [@GlobalMinDate] > 20240101 && [@HasJune1Record] && NOT(ISBLANK('Table'[Name])) ) RETURN COUNTROWS(ValidNames)
说明:先按Name分组预计算两个关键值——全局最小Date、是否存在20240601记录,再过滤符合条件的Name并计数。这种方式先聚合再过滤,避免逐行扫描,更适配百万级大表。
方法2:CALCULATE+ALL(简洁写法)
Valid Name Count = CALCULATE( DISTINCTCOUNTNOTBLANK('Table'[Name]), 'Table'[Date] = 20240601, FILTER( ALL('Table'[Name]), CALCULATE(MIN('Table'[Date]), ALL('Table'[Date])) > 20240101 ) )
说明:通过ALL('Table'[Date])让内层MIN计算不受外层Date筛选影响,确保拿到每个Name的全局最小Date,再筛选出符合条件的Name,最后结合Date=20240601统计去重计数。
内容的提问来源于stack exchange,提问作者ap3x
相关产品推荐
相关产品推荐

