首页 文章

命名列时出现U-SQL错误

提问于
浏览
1

我有一个JSON,其中字段的顺序不固定 .

即我可以 [A, B, C] or [B, C, A]

所有A,B,C都是json对象,其形式为{Name:x,Value:y} .

因此,当我使用USQL提取JSON(我不知道他们的顺序)并将其放入CSV(我将需要列名称)时:

@output =
    SELECT
        A["Value"] ?? "0" AS CAST ### (("System_" + A["Name"]) AS STRING), 
        B["Value"] ?? "0" AS "System_" + B["Name"],
        System_da

所以,我试图将列名作为JSON中的“名称”字段 .

但我在####上面得到错误:

Message

syntax error. Expected one of: FROM ',' EXCEPT GROUP HAVING INTERSECT OPTION ORDER OUTER UNION UNION WHERE ';' ')' 

Resolution
Correct the script syntax, using expected token(s) as a guide.

Description

Invalid syntax found in the script.

Details
at token '(', line 74
near the ###:
**************

我不允许“动态地”输入正确的列名,这是我的问题的绝对必要 .

Input: [A, B, C,], [C, B, A]

Output:        A.name B.name C.name
Row 1's values
Row 2's values

1 回答

  • 3

    这个

    @output =
    SELECT
        A["Value"] ?? "0" AS CAST ### (("System_" + A["Name"]) AS STRING), 
        B["Value"] ?? "0" AS "System_" + B["Name"],
        System_da
    

    不是有效的SELECT子句(在U-SQL和我所知道的任何其他SQL方言中都没有) .

    什么是JSON数组?它是键/值对吗?还是位置?或者数组中的单个值是否要有标记,以确定它是否存在于数组中?

    从你的例子来看,你似乎想要这样的东西:

    输入:

    [["A","B","C"],["C","D","B"]]
    

    输出:

    A     B    C    D
     true  true true false
     false true true true
    

    如果是这种情况,我会把它写成:

    REFERENCE ASSEMBLY [Newtonsoft.Json];
    REFERENCE ASSEMBLY [Microsoft.Analytics.Samples.Formats]; 
    
    USING Microsoft.Analytics.Samples.Formats.Json;
    
    @input = 
      SELECT "[[\"A\", \"B\", \"C\"],[\"C\", \"D\", \"B\"]]" AS json 
      FROM (VALUES (1)) AS T(x);
    
    @data = 
      SELECT JsonFunctions.JsonTuple(arrstring) AS a 
      FROM @input CROSS APPLY EXPLODE( JsonFunctions.JsonTuple(json).Values) AS T(arrstring);
    
    @data = 
      SELECT a.Contains("A") AS A, a.Contains("B") AS B, a.Contains("C") AS C, a.Contains("D") AS D 
      FROM (SELECT a.Values AS a FROM @data) AS t;
    
    OUTPUT @data
    TO "/output/data.csv"
    USING Outputters.Csv(outputHeader : true);
    

    如果您需要更动态的内容,请使用生成的 SqlArraySqlMap 或使用上述方法生成脚本 .

    但是,我想知道为什么你会首先以这种方式建模你的信息 . 我建议找一种更合适的方法来标记JSON中值的存在 .

    UPDATE :我错过了你关于内部数组成员是一个具有两个键值对的对象的评论,其中一个总是被称为name(对于属性),一个总是被称为属性值的值 . 所以这是这种情况的答案 .

    第一:使用 {"Name": "propname", "Value" : "value"} 在JSON中建模键值对完全滥用JSON的灵活建模功能,不应该这样做 . 如果可以的话,请使用 {"propname" : "value"} .

    因此,更改输入,以下将为您提供旋转值 . 请注意,您需要提前知道这些值,并且有几个选项可用于如何进行数据透视 . 我在创建新 SqlMap 实例的语句中执行此操作以减少过度建模,然后在下一个 SELECT 中从 Map 中获取值 .

    REFERENCE ASSEMBLY [Newtonsoft.Json];
    REFERENCE ASSEMBLY [Microsoft.Analytics.Samples.Formats]; 
    
    USING Microsoft.Analytics.Samples.Formats.Json;
    
    @input = 
      SELECT "[[{\"Name\":\"A\", \"Value\": 1}, {\"Name\": \"B\", \"Value\": 2}, {\"Name\": \"C\", \"Value\":3 }], [{\"Name\":\"C\", \"Value\": 4}, {\"Name\":\"D\", \"Value\": 5}, {\"Name\":\"B\", \"Value\": 6}]]" AS json 
      FROM (VALUES (1)) AS T(x);
    
    @data = 
      SELECT JsonFunctions.JsonTuple(arrstring) AS a
      FROM @input CROSS APPLY EXPLODE( JsonFunctions.JsonTuple(json)) AS T(rowid, arrstring);
    
    @data =
      SELECT new SqlMap<string, string>( 
                 a.Values.Select((kvp) => 
                     new KeyValuePair<string, string>(
                           JsonFunctions.JsonTuple(kvp)["Name"]
                         , JsonFunctions.JsonTuple(kvp)["Value"])
             )) AS kvp
      FROM @data;
    
    @data =
      SELECT kvp["A"] AS A,
             kvp["B"] AS B,
             kvp["C"] AS C,
             kvp["D"] AS D
      FROM @data;
    
    OUTPUT @data
    TO "/output/data.csv"
    USING Outputters.Csv(outputHeader : true);
    

相关问题