3

我已经阅读了Power Query的M”语言的语言规范,并且遇到了开放记录类型。我的理解是开放类型允许其他字段,但我没有具体理解这意味着什么。

声明正常(关闭)记录的方法很简单

myRecord = [name = "MyName", Age = 30]

从语言规范(5.4:记录类型):

myRecordType1 = type [Name = text, Age = number]       // Closed Record _type_
myRecordType2 = type [Name = text, Age = number, ...]  // Open Record _type_

然而,

myRecord = [Name = "MyName", Age = 30, ...] // Not valid code

所以这个概念似乎只是关于自定义记录类型,而不是一般的记录,但我不知道如何处理它。我试过这个:

testFunc = (inputArg as myRecordType2) => 1 // Not valid code

...期望它可能使该函数只接受带有姓名和年龄字段的记录,以及可选的其他字段,但不接受。认为它可能不适用于as关键字,但即使这样也不起作用:

testTable = Table.AddColumn(Table.FromRecords({[A=1]}), "newcol", each [Name="MyName", Age=30], type myRecordType1) // Not valid code

有人可以说明一个用例(案例)吗?我错过了语言规范中的某些内容吗?

4

2 回答 2

3

我的解释如下。任何评论表示赞赏(甚至是其他想法)。

类型是值的分类。有两种风格:原始类型(数字、文本等)和自定义类型,例如特定的表格类型或记录类型。

例如,表类型是列名、类型和任何键值的集合。可以先指定表类型,然后在创建表时使用:

Tabeltype = type table[Key = number, Value = text],
TabletypeWithKey =  Type.AddTableKey(Tabeltype,{"Key"},true), 
TableWithKey = #table(TabletypeWithKey, {{1, "A"},{2, "B"}, {3, "C"}})

同样,您可以创建记录类型。

但是,创建记录时不能直接使用记录类型。您可以使用 Value.ReplaceType 将类型“赋予”一个值,例如,将记录类型赋予记录,前提是该记录类型是封闭的并且没有可选字段。下面代码中的示例。

我希望有可能验证一个值是否与特定类型匹配,但这只能用原始类型来完成(使用关键字“is”或“as”或“Type.Is”)。

因此,根据我的解释,我创建了下面的代码来检查记录与记录类型的一致性:我不能保证它是完整的证明。目前它是一个查询,因此您可以查看正在发生的事情,但您可以轻松地将其转换为一个函数,并在当前注释掉的代码的下半部分使用示例。

// Mext 2 lines to be decommented to turn the code into a function
//let
//    fnCheckConformity = (Record1 as record, RecordType as type) as logical =>
let
    // Next 2 lines to be removed when turning this code into a function
    Record1 = [x = 1, A = 3, B = 4],
    RecordType = type [x = number, optional y = text,...],
    RecordTypeFields = Type.RecordFields(RecordType),
    ToTable = Record.ToTable(RecordTypeFields),
    RecordTypeTable = Table.ExpandRecordColumn(ToTable, "Value", {"Optional", "Type"}, {"Optional", "Type"}),
    RecordTable = Table.FromColumns({Record.FieldNames(Record1),Record.FieldValues(Record1)},{"Record FieldName", "Record FieldValue"}),
    JoinedTable = Table.Join(RecordTypeTable, "Name", RecordTable, "Record FieldName", JoinKind.FullOuter),
    ConformityCheck = Table.AddColumn(JoinedTable, "Conform", 
                        each if [Optional] = null then Type.IsOpenRecord(RecordType) else
                             if [Optional] then true else
                             if [Record FieldValue] <> null then Value.Is([Record FieldValue], [Type]) else
                             false),
    Result = List.AllTrue(ConformityCheck[Conform])
in
    Result
// Add a comma after Result when turning the code above into a function
/* The code below can be used when turning the code above into a function.
// Examples:
    OpenRecordType = type [x = number, optional y = text,...],
    ClosedRecordType = type [x = number, y = text],
    RecordA = [x = 1],
    RecordB = [x = 1, A = 3, B = 4],
    RecordC = [x = 1, y = "MarcelBeug"],
//  RecordC is ascribed type ClosedRecordType:
    RecordCTyped = Value.ReplaceType(RecordC, ClosedRecordType),
    Conformity1 = fnCheckConformity(RecordA, OpenRecordType),   // true
    Conformity2 = fnCheckConformity(RecordA, ClosedRecordType), // false
    Conformity3 = fnCheckConformity(RecordB, OpenRecordType),   // true
    Conformity4 = fnCheckConformity(RecordB, ClosedRecordType), // false
    Conformity5 = fnCheckConformity(RecordC, OpenRecordType)    // true
in
    Conformity5 */
于 2016-12-01T03:01:35.347 回答
1

Marcel 的回答很棒,但我可以添加更多上下文。

确实,今天“M”中的开放记录类型没有太多用途。

它可能有用的一个地方是,如果我们有“不规则”表的概念,例如这个 CSV,在不同的行中有两个、三个和四个数据字段。

A,B,C
1,2
1,2,3
1,2,3,4

将此 CSV 加载到 PQ 编辑器 / Excel / PowerBI Desktop / powerbi.com 可能会起作用,但它不适合表值。在今天的“M”设计中,表基本上是包含非可选字段的已关闭记录的列表(因此您不能让表行的字段多于或少于表列)。

Azure Table 或 OData 等其他一些数据源也可能使用了不规则表。现在,我们将返回一个包含一些固定列的表,以及一个记录列[Content][Open Types].

于 2016-12-01T17:41:05.747 回答