#excel #powerquery
Вопрос:
С Table.NestedJoin JoinKind.FullOuter
, a null
может быть записано в столбцы, когда в правой таблице «ключ» есть значение, которого нет в левой таблице «ключ».
Однако, в отличие от значения null, которое находится в левой таблице, поскольку ячейка пуста, это созданное значение null не соответствует формуле = True [column] = null
.
Например:
Таблица 1
Обратите внимание на нуль в строке 3
Объединенный Стол
Значение null в строке 5 было создано в результате объединения
Пользовательский столбец
добавлено с формулой =[A]=null
обратите внимание на различные результаты для null
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"
Мы были бы признательны за разъяснения и предложения относительно того, как с этим бороться.
Редактирование В дополнение к вышесказанному, выполнение a Replace
также заменит null
только строку 3, а не null
строку 5. Кажется, в этих двух нулях есть что-то другое.
Примечание: Если я разверну таблицу, значение null в столбце A теперь будет проверяться правильно.
Комментарии:
1. Из любопытства, каков будет результат , если вы используете
[A] is null
или даже([A] as null) = null
?2. @JeroenMostert, это тоже не сработало. Один из способов , который, казалось, работал с обоими нулевыми s, был
List.Count(List.RemoveNulls({[A]}))=0
, но это кажется довольно неудобным методом и, конечно, не соответствует документации, которую я нашел. И он не решает другие проблемы, такие как неспособностьReplace
работать.3. Значит, имеет все признаки жука. Я думал, что, возможно, каким-то образом
nothing
была создана ценность, но это должно было быть устранено с помощью явногоnull
преобразования. Сравнение сnull
должно давать только atrue
илиfalse
независимо от используемых типов, нетnull
, так как PQ не использует трехзначную логику SQL.4. @JeroenMostert Проблема, вероятно, является следствием модели оценки PQ. В любом случае, при принудительном вычислении с помощью буферной функции два нуля ведут себя одинаково. Смотрите мой ответ ниже.
Ответ №1:
Задав тот же вопрос на форуме вопросов и ответов Microsoft, я указал на возможность проблемы с моделью оценки запросов питания, а также на эту статью о ленивой оценке и сворачивании запросов в Power BI/Power Query.
Принудительно оценивая таблицу с Table.Buffer
помощью , оба значения null теперь ведут себя одинаково.
Так:
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
также заставит провести оценку. Так что вместо стола.Буфер, также работает следующее:
...
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)
Комментарии:
1. Довольно нелогично-вы могли бы ожидать, что ленивая оценка перестанет быть ленивой, как только вы действительно сравните значение столбца, так как в этот момент оно нам явно нужно 😛 Второй подход, возможно, является лучшим с точки зрения предоставления PQ наибольшей свободы действий для ленивой оценки других столбцов (поскольку мы запрашиваем только значение одного), хотя на практике это может не иметь значения.
Ответ №2:
Очень интересный случай. Действительно, поведение последнего значения null противоречит здравому смыслу в большинстве возможных реализаций. Если вы хотите получить одинаковое поведение для обоих типов нулей, попробуйте этот подход:
= Table.AddColumn(combo, "test", each [A] ?? 10)
Довольно интересно, что аналогичный код не работает:
= Table.AddColumn(combo, "test", each if [A] = null then 10 else [A])
Более того, если мы хотим улучшить предыдущий код, используя первый синтаксис, мы все равно получим неожиданный результат (10 вместо 20 для последнего нуля).:
= Table.AddColumn(combo, "test", each if [A] = null then 10 else [A] ?? 20)
Любопытно, что применение оператора ?? также устраняет проблему с начальным столбцом. Теперь в столбце есть обычные нули:
= Table.AddColumn(add, "test2", each [A] = null)
Поэтому, если нам не нужны никакие вычисления и мы просто хотим исправить недопустимые нули, мы можем использовать такой код:
= Table.TransformColumns(combo, {"A", each _ ?? _})
Столбец не имеет значения, и для объединенного столбца результат тот же самый:
transform = Table.TransformColumns(combo, {"joined", each _ ?? _}),
add = Table.AddColumn(transform, "test", each [A] = null)
Комментарии:
1. Проблема может быть связана с Моделью оценки. Смотрите мой ответ ниже
2. Я не знаю, как правильно назвать источник проблемы, но факт в том, что после соединения с FullOuter у нас есть дефектный null, у которого даже нет типа (это становится ясно после применения этого кода, например — Table. TransformColumns(комбинация, {«A», Значение. Тип})). О преодолении этой проблемы, возможно, это вопрос вкуса, но я бы предпочел решение с помощью ?? оператор, итак, я расширил свой ответ.
3. Я бы подумал, что любая операция, которая требует тщательной оценки, сработает.