我有一个名为“ Table1”的表,其中有两列,分别是“名称”和“日期”。
在Power Query Editor中,我想创建一个名为“ Last Date”的自定义列,以查找给定名称上次出现时的最新日期。
例如,B第一次出现在5/7/2019,然后出现在11/8/2019,最后出现在17/9/2019。因此,当日期为11/8/2019时B的最后日期为5/7/2019,而日期为17/9/2019时B的最后日期为11/8/2019。请参见下面的示例。
我在线上做了一些研究,但是对自定义函数,VAR,Measure,MAXX,CALCULATE,FILTER等感到困惑。
我不熟悉DAX或Advanced DAX编辑器,因此,请尽可能提供详细的答案或明确的步骤来应用您的解决方案。
让我知道我是否不清楚。否则,您的及时帮助将不胜感激!
答案 0 :(得分:1)
Power Query和Power BI是两个不同的工具。
Power Query用于处理数据。它使用称为“ m”的语言。例如,如果您需要导入和合并文件,修复不良数据等,这就是您所使用的。
Power BI旨在分析数据。它使用称为“ DAX”的语言。大多数时候,Power BI / DAX对于设计交互式分析非常有用-可以响应切片器,过滤器等的报告。
有些人使用DAX而不是Power Query来增强其数据-例如添加计算列。我个人认为这是个坏主意,但Power Query / m可能对他们来说太不直观,而DAX则更容易。我将解释如何使用DAX添加计算列。如果出于某种原因您更喜欢Power Query,请在您的问题中提及。
首先,您必须在Power BI主窗口中,而不在Power Query窗口中。转到数据模型,然后选择表。在“模型”选项卡上,单击“添加列”。输入DAX公式:
Last Date =
VAR Current_Date = Table1[Date]
VAR Current_Name = Table1[Name]
RETURN
CALCULATE( MAX(Table1[Date]),
Table1[Date] < Current_Date,
Table1[Name] = Current_Name )
该公式将为每个名称生成一个带有上一个日期的新列。
工作原理:
例如,对于名称“ B”,首先突出显示:它将首先过滤表,仅保留名称=“ B”的记录(3个记录)。然后,它将进一步过滤这3条记录,以查找日期<11/08/2019,这是一条记录:5/07/2019。
作为旁注,我建议至少阅读一本有关Power BI / DAX的好书,或参加在线培训课程。这个工具并不简单,如果尝试通过反复试验来学习它,将会浪费很多时间。
答案 1 :(得分:1)
自定义函数可能类似于:
let
AddLastDateColumn = (someTable as table) as table =>
let
initialHeaders = Table.ColumnNames(someTable),
sorted = Table.Sort(someTable, {{"Date", Order.Ascending}, {"Name", Order.Ascending}}),
merged = Table.NestedJoin(sorted, {"Name"}, sorted, {"Name"}, "$joined", JoinKind.LeftOuter),
lastDateColumn = Table.AddColumn(merged, "Last Date", each
let
maxDate = [Date],
filtered = Table.SelectRows([#"$joined"], each [Date] < maxDate),
lastRow = if not Table.IsEmpty(filtered) then Table.Last(filtered)[Date] else null // Could use Table.Max, but data is already sorted.
in lastRow,
type nullable date),
dropColumns = Table.SelectColumns(lastDateColumn, initialHeaders & {"Last Date"})
in dropColumns
in
AddLastDateColumn
如果将以上内容另存为自己的查询,则可以在其他查询中对其进行访问。例如,如果将以上内容另存为名为AddLastDateColumn
的查询,则可以访问
在其他查询中(如下所示):
let
sourceTable =
let
nameColumn = {"A", "B", "C", "D", "E", "F", "G", "A", "B", "C", "D", "E", "F", "G", "A", "B", "C", "D", "E", "F", "G"},
dateColumn = {#date(2019,7,1), #date(2019,7,5), #date(2019,7,14), #date(2019,7,23), #date(2019,7,24), #date(2019,8,1), #date(2019,8,5), #date(2019,8,10), #date(2019,8,11), #date(2019,8,17), #date(2019,8,23), #date(2019,8,25), #date(2019,9,3), #date(2019,9,4), #date(2019,9,13), #date(2019,9,17), #date(2019,9,23), #date(2019,9,27), #date(2019,9,28), #date(2019,10,6), #date(2019,10,9)},
toTable = Table.FromColumns({nameColumn, dateColumn}, type table [Name = text, Date = date])
in toTable,
invokeFunction = AddLastDateColumn(sourceTable)
in
invokeFunction
我正在查看Table.NestedJoin
(https://docs.microsoft.com/en-us/powerquery-m/table-nestedjoin)的文档。似乎有一个名为keyEqualityComparers
的参数:
可以包括一组可选的
keyEqualityComparers
,以指定如何比较键列。
我没有时间研究其功能和所需的语法,但也许可以用来更优雅地指定JOIN标准:“ Name
必须完全匹配。{{1 }}必须是小于Right Date
“ 的最大日期。
无论如何,我认为上述功能应该可以满足您的要求。
答案 2 :(得分:0)
在RADO朝着正确的方向发展之后,我使用M语言和内置GUI搜索了更多类似的Power Query案例,找到了解决问题的方法。
1)首先按以下顺序对我的表进行升序排序:名称,日期;
2)添加两个索引列,一个以0开头,另一个以1开头,然后将匹配索引列0的表本身与索引列1合并;
3)展开合并的列[Name.1]和[Date.1],然后使用以下 if 函数添加一个名为“ Last Date”的自定义列
if [Name]=[Name.1] then [Date.1] else null
4)删除其他列,只需保留[名称],[日期]和[最后日期]列即可。
如果我有几个需要相同操作的表,则上述方法有点乏味。如果有人可以使用单个查询提供“自定义功能”解决方案,并将其应用于其他表,将不胜感激!