【问题标题】:Power Query: Detect null created by Table.NestedJoin JoinKind.FullOuterPower Query:检测由 Table.NestedJoin JoinKind.FullOuter 创建的 null
【发布时间】:2021-05-27 23:36:40
【问题描述】:

使用Table.NestedJoin JoinKind.FullOuter,当右表“key”中存在左表“key”中不存在的值时,可以将null写入列。

但是,与左表中的 null 不同,因为单元格为空,此创建的 null 不 = True 与公式 [column] = null

例如:

Table1
注意第 3 行中的空值

Table2

联接表
第 5 行中的空值是联接的结果

自定义列
添加了公式 =[A]=null
注意 null 的不同结果
@987654324 @

MCode 重现上述

let
    Source1 = Table.FromRecords({
        [A="a"],
        [A="b"],
        [A=null],
        [A="c"]
    }),
    type1 = Table.TransformColumnTypes(Source1,{"A", type text}),
    Source2 = Table.FromRecords({
        [A="c"],
        [A="d"]
    }),
    type2 = Table.TransformColumnTypes(Source2,{"A", type text}),

    combo = Table.NestedJoin(type1,"A",type2,"A","joined",JoinKind.FullOuter),
    #"Added Custom" = Table.AddColumn(combo, "Custom", each [A]=null)
in
    #"Added Custom"

我们将不胜感激有关如何处理此问题的说明和建议。

编辑 除了上述之外,执行Replace 也只会替换第 3 行中的 null,而不是第 5 行中的 null。似乎有一些不同之处这两个空值。

注意:如果我展开表格,A列中的null现在将正确测试。

【问题讨论】:

  • 出于好奇,如果你使用[A] is null,甚至([A] as null) = null,结果是什么?
  • @JeroenMostert 那也没用。 List.Count(List.RemoveNulls({[A]}))=0 似乎适用于两个 null 的一种方法,但这似乎是一种相当尴尬的方法,而且肯定不符合我找到的文档。它不处理其他问题,例如 Replace 无法工作。
  • 那么就具有错误的所有特征。我当时在想,可能以某种方式创建了 nothing 值,但应该通过明确的 null 转换来消除它。与null 的比较应该只产生truefalse 而不管涉及的类型,而不是null,因为PQ 不使用SQL 的三值逻辑。
  • @JeroenMostert 这个问题可能是 PQ 评估模型的结果。无论如何,通过使用 Buffer 函数强制求值,两个 null 的行为相同。请参阅下面的答案。

标签: excel powerquery


【解决方案1】:

在 Microsoft 问答论坛上提出同样的问题,我指出 Power Query Evaluation modelLazy Evaluation and Query Folding in Power BI/Power Query 上的这篇文章可能存在问题。

通过强制评估带有Table.Buffer 的表,现在两个空值的行为相同。

所以:

let
    Source1 = Table.FromRecords({
        [A="a"],
        [A="b"],
        [A=null],
        [A="c"]
    }),
    type1 = Table.TransformColumnTypes(Source1,{"A", type text}),
    Source2 = Table.FromRecords({
        [A="c"],
        [A="d"]
    }),
    type2 = Table.TransformColumnTypes(Source2,{"A", type text}),

//Table.Buffer forces evaluation
    combo = Table.Buffer(Table.NestedJoin(type1,"A",type2,"A","joined",JoinKind.FullOuter)),

//IsItNull now works
    IsItNull = Table.AddColumn(combo, "[A] = null", each [A] = null)
  in
    IsItNull

try ... otherwise 似乎也会强制进行评估。因此,除了 Table.Buffer,以下也可以:

    ...
    combo = Table.NestedJoin(type1,"A",type2,"A","joined",JoinKind.FullOuter),
//try ... otherwise seems to force Evaluation
    IsItNull = Table.AddColumn(combo, "[A] = null", each try [A] = null otherwise null)

【讨论】:

  • 相当违反直觉——一旦你真正比较了一个列值,你会期望惰性求值不再是惰性的,因为那时我们显然需要它:P 就给出而言,第二种方法可以说是最好的PQ 是保持对其他列的评估懒惰的最大余地(因为我们只要求一个的值),尽管它在实践中可能没有什么不同。
【解决方案2】:

非常有趣的案例。实际上,在大多数可能的实现中,last null 的行为是违反直觉的。如果您希望对两种空值都获得相同的行为,请尝试以下方法:

= Table.AddColumn(combo, "test", each [A] ?? 10)

很有意思,类似的代码不起作用:

= Table.AddColumn(combo, "test", each if [A] = null then 10 else [A])

此外,如果我们想通过使用第一个语法来改进之前的代码,我们仍然会得到意想不到的结果(最后一个 null 是 10 而不是 20):

= Table.AddColumn(combo, "test", each if [A] = null then 10 else [A] ?? 20)

Сurious,应用 ?? 运算符也解决了初始列的问题。现在 A 列中有常规的空值:

= Table.AddColumn(add, "test2", each [A] = null)

所以,如果我们不需要任何计算,只想修复无效的空值,我们可以使用这样的代码:

= Table.TransformColumns(combo, {"A", each _ ?? _})

列无关紧要,对于 joined 列,结果是相同的:

transform = Table.TransformColumns(combo, {"joined", each _ ?? _}),
add = Table.AddColumn(transform, "test", each [A] = null)

【讨论】:

  • 问题可能与评估模型有关。请参阅下面的答案
  • 我不知道如何正确命名问题的根源,但事实是在FullOuter join之后我们有缺陷的null,甚至没有类型(应用此代码后变得清晰,例如 - Table.TransformColumns(combo, {"A", Value.Type}))。关于克服这个问题,这可能是一个品味问题,但我更喜欢 ??运营商,所以,我扩展了我的答案。
  • 我认为任何强制进行急切评估的操作都会起作用。
猜你喜欢
  • 1970-01-01
  • 2016-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-01
  • 1970-01-01
相关资源
最近更新 更多