PowerQuery-根据给定值和当前日期查找最新日期

时间:2019-07-11 06:14:59

标签: powerbi dax powerquery m

我有一个名为“ 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。请参见下面的示例。

enter image description here

我在线上做了一些研究,但是对自定义函数,VAR,Measure,MAXX,CALCULATE,FILTER等感到困惑。

我不熟悉DAX或Advanced DAX编辑器,因此,请尽可能提供详细的答案或明确的步骤来应用您的解决方案。

让我知道我是否不清楚。否则,您的及时帮助将不胜感激!

3 个答案:

答案 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 )

该公式将为每个名称生成一个带有上一个日期的新列。

工作原理:

  • 计算列时,Power BI逐记录迭代表记录。对于每条记录,我们将其日期存储在变量“ Current_Date”中,并将其名称存储在“ Current_Name”中;
  • 然后,我们需要找到一个日期,该日期是:a)小于current_date,并且b)仅针对当前名称。这是通过使用2个过滤器计算MAX日期来实现的:日期必须为<然后是Current_Date,名称必须为= 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.NestedJoinhttps://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)删除其他列,只需保留[名称],[日期]和[最后日期]列即可。

如果我有几个需要相同操作的表,则上述方法有点乏味。如果有人可以使用单个查询提供“自定义功能”解决方案,并将其应用于其他表,将不胜感激!