Ошибка 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

Итак, я пытаюсь поместить имя столбца в поле «Имя» в 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

person Rafael    schedule 19.03.2018    source источник
comment
Это действительно {A, B, C} или это массив? Не могли бы вы предоставить действительный пример документа JSON и желаемый результат?   -  person Peter Bons    schedule 19.03.2018
comment
@PeterBons: да, извините, он имеет форму [A, B, C], где A, B, C - объекты json в форме {Name: x, Value: y}   -  person Rafael    schedule 19.03.2018
comment
@PeterBons, я включил пару простых входов и выходов   -  person Rafael    schedule 19.03.2018


Ответы (1)


Этот

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

Если вам нужно что-то более динамичное, используйте полученный SqlArray или SqlMap или используйте описанный выше подход для создания сценария.

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

ОБНОВЛЕНИЕ: я пропустил ваш комментарий о том, что элементы внутреннего массива представляют собой объект с двумя парами ключ-значение, где одна всегда называется именем (для свойства), а другая всегда называется значением для значения свойства. Итак, вот ответ на этот случай.

Во-первых: моделирование пар ключ-значение в JSON с использованием {"Name": "propname", "Value" : "value"} является полным злоупотреблением гибкими возможностями моделирования 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);
person Michael Rys    schedule 19.03.2018
comment
Я думаю, это дубликат этого вопроса: stackoverflow.com/questions/49137679/ и, может быть, почему они опубликовали снова, может быть, из-за порядковых номеров? - person wBob; 20.03.2018
comment
Я вижу отношения. Извините, я не взглянул на другой. И я вижу, что пропустил комментарий {Name: name, Value: val}. Опять же, это неправильный способ моделирования пар ключ-значение на таком языке, как JSON. Я также обновляю свой пример сценария для его примера, но настоятельно рекомендую моделировать данные другим способом. - person Michael Rys; 20.03.2018