Введение

Обзор

Microsoft Power Query предоставляет мощный интерфейс получения данных, охватывающий множество функций. Основная возможность Power Query — фильтрация и объединение данных из одного или нескольких расширенных источников данных. Любые такие мешажи данных выражаются с помощью языка формул Power Query (неофициально известного как "M"). Power Query внедряет документы M в широкий спектр продуктов Майкрософт, в том числе Excel, Power BI, Analysis Services и Dataverse, чтобы включить повторяемые mashup данных.

Этот документ содержит спецификацию для M. После краткого введения, направленного на создание первой интуиции и знакомство с языком, документ охватывает язык точно в нескольких прогрессивных шагах:

  1. Лексическая структура определяет набор текстов, которые лексически допустимы.

  2. Значения, выражения, среды и переменные, идентификаторы и модель оценки формируют основные понятия языка.

  3. Подробная спецификация значений, как примитивных, так и структурированных, определяет целевой домен языка.

  4. Значения имеют типы, сами по себе специальный вид значения, которые характеризуют основные типы значений и несут дополнительные метаданные, относящиеся к формам структурированных значений.

  5. Набор операторов в M определяет, какие виды выражений можно сформировать.

  6. Функции, другие специальные значения, предоставляют основу для богатой стандартной библиотеки для M и позволяют добавлять новые абстракции.

  7. Ошибки могут возникать при применении операторов или функций во время вычисления выражений. Хотя ошибки не являются значениями, существуют способы обработки ошибок, которые сопоставляют ошибки с значениями.

  8. Пусть выражения позволяют вводить вспомогательные определения, используемые для создания сложных выражений в небольших шагах.

  9. Если выражения поддерживают условную оценку.

  10. Разделы предоставляют простой механизм модульности. (Разделы еще не используются Power Query.)

  11. Наконец, консолидированная грамматика собирает фрагменты грамматики из всех остальных разделов этого документа в одно полное определение.

Для теоретиков языка компьютеров: язык формул, указанный в этом документе, является в основном чистым, более высоким, динамически типизированным, частично отложенным функциональным языком.

Выражения и значения

Центральная конструкция в M — это выражение. Выражение можно вычислять (вычислять), возвращая одно значение.

Хотя многие значения могут быть записаны буквально как выражение, значение не является выражением. Например, выражение 1 оценивается значением 1; выражения 1+1 вычисляют значение 2. Это различие тонко, но важно. Выражения — это рецепты для оценки; значения — это результаты оценки.

В следующих примерах показаны различные типы значений, доступных в M. Как соглашение, значение записывается с помощью литеральной формы, в которой они будут отображаться в выражении, которое оценивает только это значение. (Обратите внимание, что указывает // начало комментария, который продолжается до конца строки.)

  • Примитивное значение — это однопартийное значение, например число, логический, текст или null. Значение NULL можно использовать для указания отсутствия любых данных.

    123                  // A number
    true                 // A logical
    "abc"                // A text
    null                 // null value
    
  • Значение списка — это упорядоченная последовательность значений. M поддерживает бесконечные списки, но если они написаны как литерал, списки имеют фиксированную длину. Фигурные фигурные скобки { и } обозначьте начало и конец списка.

    {123, true, "A"}     // list containing a number, a logical, and 
                          //     a text 
    {1, 2, 3}            // list of three numbers 
    
  • Запись — это набор полей. Поле — это пара "имя-значение", где имя является текстовым значением, уникальным в записи поля. Синтаксис литерала для значений записей позволяет записывать имена без кавычки, форму также называют идентификаторами. Ниже показана запись, содержащая три поля с именем "", "AB" и "C", которые имеют значения 1, 2и 3.

    [ 
          A = 1,  
          B = 2,  
          C = 3 
    ]
    
  • Таблица — это набор значений, упорядоченных по столбцам (которые определяются по имени) и строкам. Нет литерального синтаксиса для создания таблицы, но существует несколько стандартных функций, которые можно использовать для создания таблиц из списков или записей.

    Например:

    #table( {"A", "B"}, { {1, 2}, {3, 4} } ) 
    

    При этом создается таблица следующей фигуры:

    Image of an example table in the M formula language.

  • Функция — это значение, которое при вызове с аргументами создает новое значение. Функция записывается путем перечисления параметров функции в круглых скобках, а затем символа =>переходов, за которым следует выражение, определяющее функцию. Это выражение обычно относится к параметрам (по имени).

    (x, y) => (x + y) / 2`
    

Оценка

Модель оценки языка M моделиируется после того, как модель оценки обычно найдена в электронных таблицах, где порядок вычисления можно определить на основе зависимостей между формулами в ячейках.

Если вы написали формулы в электронной таблице, например Excel, вы можете распознать формулы слева в результате значений справа при вычислении:

Image of the formulas on the right resulting in the values on the left.

В M части выражения могут ссылаться на другие части выражения по имени, а процесс оценки автоматически определяет порядок вычисления ссылочных выражений.

Запись можно использовать для создания выражения, эквивалентного предыдущему примеру электронной таблицы. При инициализации значения поля можно ссылаться на другие поля в записи, используя имя поля следующим образом:

[  
    A1 = A2 * 2,  
    A2 = A3 + 1,  
    A3 = 1  
]

Приведенное выше выражение эквивалентно следующему (в том, что оба оцениваются равными значениями):

[  
    A1 = 4,  
    A2 = 2,  
    A3 = 1  
]

Записи могут содержаться внутри или вложены в другие записи. Оператор подстановки ([]) можно использовать для доступа к полям записи по имени. Например, следующая запись имеет поле с именем Sales записи, а поле с именем Total , которое обращается к FirstHalf полям и SecondHalf полям Sales записи:

[  
    Sales = [ FirstHalf = 1000, SecondHalf = 1100 ], 
    Total = Sales[FirstHalf] + Sales[SecondHalf] 
]

Приведенное выше выражение эквивалентно следующему при вычислении:

[  
    Sales = [ FirstHalf = 1000, SecondHalf = 1100 ], 
    Total = 2100 
]

Записи также могут содержаться в списках. Оператор позиционного индекса ({}) можно использовать для доступа к элементу в списке по числовой индексу. Значения в списке ссылаются на использование отсчитываемого от нуля индекса с начала списка. Например, индексы 0 и 1 используются для ссылки на первые и второй элементы в списке ниже:

[ 
    Sales =  
        {  
            [  
                Year = 2007,  
                FirstHalf = 1000,  
                SecondHalf = 1100, 
                Total = FirstHalf + SecondHalf // 2100 
            ], 
            [  
                Year = 2008,  
                FirstHalf = 1200,  
                SecondHalf = 1300, 
                Total = FirstHalf + SecondHalf // 2500 
            ]  
        }, 
    TotalSales = Sales{0}[Total] + Sales{1}[Total] // 4600 
]

Выражения элементов списка и записи (а также разрешенные выражения) оцениваются с помощью отложенной оценки, что означает, что они оцениваются только по мере необходимости. Все остальные выражения оцениваются с помощью стремленной оценки, что означает, что они вычисляются немедленно при обнаружении во время процесса оценки. Хороший способ думать об этом заключается в том, чтобы помнить, что оценка списка или выражения записи возвращает значение списка или записи, которое само по себе запоминает, как его элементы списка или поля записи должны быть вычисляться при запросе (по запросу или операторам индекса).

Функции

В M функция — это сопоставление из набора входных значений с одним выходным значением. Функция записывается путем первого именования необходимого набора входных значений (параметров функции), а затем предоставляет выражение, вычисляющее результат функции с помощью этих входных значений (текст функции) после символа переходов (=>). Например:

(x) => x + 1                    // function that adds one to a value 
(x, y) =>  x + y                // function that adds two values

Функция — это значение так же, как число или текстовое значение. В следующем примере показана функция, которая является значением поля Add, которое затем вызывается или выполняется из нескольких других полей. При вызове функции указывается набор значений, которые логически заменяются необходимым набором входных значений в выражении тела функции.

[ 
    Add = (x, y) => x + y,
    OnePlusOne = Add(1, 1),     // 2 
    OnePlusTwo = Add(1, 2)      // 3
]

Библиотека

M включает общий набор определений, доступных для использования из выражения, называемого стандартной библиотекой, или просто библиотекой для краткого. Эти определения состоят из набора именованных значений. Имена значений, предоставляемых библиотекой, доступны для использования в выражении без явного определения выражением. Например:

Number.E                        // Euler's number e (2.7182...) 
Text.PositionOf("Hello", "ll")  // 2

Операторы

M включает набор операторов, которые можно использовать в выражениях. Операторы применяются к операндам для формирования символьных выражений . Например, в выражении 1 + 2 числа 1 и операнды, 2 а оператор — оператор сложения (+).

Значение оператора может отличаться в зависимости от типа значений операндов. Например, оператор "плюс" можно использовать с другими типами значений помимо чисел:

1 + 2                   // numeric addition: 3 
#time(12,23,0) + #duration(0,0,2,0) 
                        // time arithmetic: #time(12,25,0)

Другим примером оператора с операндом в зависимости от значения является оператор сочетания (&):

"A" & "BC"              // text concatenation: "ABC" 
{1} & {2, 3}            // list concatenation: {1, 2, 3} 
[ a = 1 ] & [ b = 2 ]   // record merge: [ a = 1, b = 2 ]

Обратите внимание, что некоторые операторы не поддерживают все сочетания значений. Например:

1 + "2"  // error: adding number and text isn't supported

Выражения, которые при вычислении сталкиваются с неопределенными условиями оператора, оцениваются в ошибках.

Метаданные

Метаданные — это сведения о значении, связанном со значением. Метаданные представляются как значение записи, называемой записью метаданных. Поля записи метаданных можно использовать для хранения метаданных для значения.

Каждое значение имеет запись метаданных. Если значение записи метаданных не указано, запись метаданных пуста (не имеет полей).

Записи метаданных предоставляют способ связывания дополнительных сведений с любым типом значения ненавязчивым способом. Связывание записи метаданных со значением не изменяет значение или его поведение.

Значение записи метаданных связано с существующим значением yx с помощью синтаксиса x meta y. Например, следующий код связывает запись метаданных с Rating текстовым значением "Mozart"и Tags полями:

"Mozart" meta [ Rating = 5, Tags = {"Classical"} ]

Для значений, которые уже содержат непустую запись метаданных, результатом применения мета является вычисление слияния записей существующей и новой записи метаданных. Например, следующие два выражения эквивалентны друг другу и предыдущему выражению:

("Mozart" meta [ Rating = 5 ]) meta [ Tags = {"Classical"} ] 
"Mozart" meta ([ Rating = 5 ] & [ Tags = {"Classical"} ])

Доступ к записи метаданных можно получить для заданного значения с помощью функции Value.Metadata . В следующем примере выражение в ComposerRating поле обращается к записи метаданных значения в Composer поле, а затем обращается к Rating полю записи метаданных.

[ 
    Composer = "Mozart" meta [ Rating = 5, Tags = {"Classical"} ], 
    ComposerRating = Value.Metadata(Composer)[Rating] // 5
]

Выражение Let

Многие примеры, показанные до сих пор, включали все литеральные значения выражения в результате выражения. Выражение let позволяет вычислять набор значений, назначать имена, а затем использовать в последующем выражении, которое следует за inэтим. Например, в нашем примере данных о продажах можно сделать следующее:

let 
    Sales2007 =  
        [  
            Year = 2007,  
            FirstHalf = 1000,  
            SecondHalf = 1100, 
            Total = FirstHalf + SecondHalf // 2100 
        ], 
    Sales2008 =  
        [  
            Year = 2008,  
            FirstHalf = 1200,  
            SecondHalf = 1300, 
            Total = FirstHalf + SecondHalf // 2500 
        ] 
  in Sales2007[Total] + Sales2008[Total] // 4600

Результат приведенного выше выражения — числовое значение (4600), вычисленное из значений, привязанных к именам Sales2007 и Sales2008.

Если выражение

Выражение if выбирает между двумя выражениями на основе логического условия. Например:

if 2 > 1 then
    2 + 2
else  
    1 + 1

Первое выражение (2 + 2) выбирается, если логическое выражение (2 > 1) имеет значение true, а второй (1 + 1) — значение false. Выбранное выражение (в данном случае 2 + 2) вычисляется и становится результатом if выражения (4).

ошибки

Ошибка — это указание на то, что процесс оценки выражения не мог создать значение.

Ошибки возникают операторами и функциями, которые сталкиваются с условиями ошибки или с помощью выражения ошибки. Ошибки обрабатываются с помощью try выражения. При возникновении ошибки указывается значение, которое можно использовать для указания причины возникновения ошибки.

let Sales = 
    [ 
        Revenue = 2000, 
        Units = 1000, 
        UnitPrice = if Units = 0 then error "No Units"
                    else Revenue / Units 
    ], 
    UnitPrice = try Number.ToText(Sales[UnitPrice])
in "Unit Price: " & 
    (if UnitPrice[HasError] then UnitPrice[Error][Message]
    else UnitPrice[Value])

Приведенный выше пример обращается к полю и форматирует Sales[UnitPrice] значение, создающее результат:

"Unit Price: 2"

Units Если поле было нулевым, то UnitPrice поле вызвало бы ошибку, которая была бы обработанаtry. После этого результирующее значение было бы следующим:

"No Units"

try Выражение преобразует правильные значения и ошибки в значение записи, указывающее, обрабатывает ли try выражение ошибку или нет, а также правильное значение или запись ошибки, извлеченную при обработке ошибки. Например, рассмотрим следующее выражение, которое вызывает ошибку, а затем обрабатывает его сразу:

try error "negative unit count"

Это выражение вычисляет следующее вложенное значение записи, объясняя [HasError][Error]подстановки полей [Message] и поля в предыдущем примере цены на единицу.

[ 
    HasError = true, 
    Error = 
        [ 
            Reason = "Expression.Error", 
            Message = "negative unit count", 
            Detail = null 
        ] 
]

Распространенным случаем является замена ошибок значениями по умолчанию. try Выражение можно использовать с необязательным otherwise предложением, чтобы обеспечить только то, что в компактной форме:

try error "negative unit count" otherwise 42 
// 42