命名列时出现U-SQL错误

时间:2018-03-19 12:09:46

标签: azure analytics azure-data-lake u-sql

我有一个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

所以,我试图将列名作为" Name" 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 ###:
**************

我不允许动态地输入正确的列名和#34;这是我的问题的绝对必要。

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

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

1 个答案:

答案 0 :(得分: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": "propname", "Value" : "value"}在JSON中建模键值对完全滥用JSON的灵活建模功能,不应该这样做。如果可以的话,请使用{"propname" : "value"}

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

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);