Запрос мощности: Обнаружение нуля, созданного таблицей.Гнездящийся джойнкинд.ФуллАутер

#excel #powerquery

Вопрос:

С Table.NestedJoin JoinKind.FullOuter , a null может быть записано в столбцы, когда в правой таблице «ключ» есть значение, которого нет в левой таблице «ключ».

Однако, в отличие от значения null, которое находится в левой таблице, поскольку ячейка пуста, это созданное значение null не соответствует формуле = True [column] = null .

Например:

Таблица 1
Обратите внимание на нуль в строке 3
введите описание изображения здесь

Таблица 2
введите описание изображения здесь

Объединенный Стол
Значение 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 должно давать только a true или 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. Я бы подумал, что любая операция, которая требует тщательной оценки, сработает.