Поворот JSON в Снежинке с возможным заявлением CASE - PullRequest
0 голосов
/ 17 апреля 2020

Я пытаюсь разобрать вложенную ниже JSON в снежинку, чтобы она отображалась в виде столбца. в основном я хочу, чтобы мои окончательные данные выглядели так. Я думаю, что подход, который я хочу использовать, это PIVOT, а затем выберите мин, но и используйте CASE, когда утверждение, но я не слишком уверен.

       Mins_FirstDoorOpened_LastDoorOpened
       2

       Mins_FirstCustomerEntered_LastCustomerEntered
       null

       Mins_FirstEmployeClockedIn_LastEmployeeClockedIn
       3
"IntervaTime": [
    {
      "FromActivity": "FirstDoorOpened",
      "Goal": "2",
      "Order": "1",
      "ToActivity": "LastDoorOpened"
    },
    {
      "FromActivity": "FirstCustomerEntered",
      "Order": "2",
      "ToActivity": "LastCustomerEntered"
    },
    {
      "FromActivity": "FirstEmployeClockedIn",
      "Goal": "9",
      "Order": "3",
      "ToActivity": "LastEmployeClockedIn"
    }, 
    ....

Ответы [ 2 ]

0 голосов
/ 18 апреля 2020

Отказ от ответственности : Я думаю, вы, возможно, направлялись в кроличью нору; Это не то, как работают реляционные наборы данных (в общем).

Кроме того, должно ли значение последней строки быть "9" (а не "3")? Вы не определили, откуда оно берется, поэтому я предположил, что это атрибут "Цель".

WITH CTE_1 AS (
  SELECT PARSE_JSON($1) AS MY_JSON
    FROM VALUES
           ($$
{
"IntervaTime": [
    {
      "FromActivity": "FirstDoorOpened",
      "Goal": "2",
      "Order": "1",
      "ToActivity": "LastDoorOpened"
    },
    {
      "FromActivity": "FirstCustomerEntered",
      "Order": "2",
      "ToActivity": "LastCustomerEntered"
    },
    {
      "FromActivity": "FirstEmployeClockedIn",
      "Goal": "9",
      "Order": "3",
      "ToActivity": "LastEmployeClockedIn"
    }
]
}
$$)
)
,CTE_2 AS (
SELECT X2.VALUE:"Order"::INTEGER AS EVENT_SEQ
      ,'Mins_' || X2.VALUE:"FromActivity"::VARCHAR || '_' || X2.VALUE:"ToActivity"::VARCHAR AS LINKED_EVENTS
      ,X2.VALUE:"Goal"::VARCHAR AS GOAL
      ,*
  FROM CTE_1 X
      ,LATERAL FLATTEN(TO_ARRAY(X.MY_JSON:"IntervaTime")) X2
)
,CTE_3 AS (
  SELECT EVENT_SEQ AS SORT1
        ,0 AS SORT2
        ,LINKED_EVENTS AS OUTPUT_STR
    FROM CTE_2
  UNION ALL
  SELECT EVENT_SEQ
        ,1
        ,GOAL
    FROM CTE_2
)
SELECT OUTPUT_STR
  FROM CTE_3
 ORDER BY SORT1
         ,SORT2
;
0 голосов
/ 17 апреля 2020

Я бы использовал UDF для этого *.

CREATE OR REPLACE FUNCTION get_interval(IntervaTime array, activity string)
  RETURNS string
  LANGUAGE JAVASCRIPT
AS
$$
  return INTERVATIME.filter(item => item.FromActivity == ACTIVITY).map(item => item.Order)[0];
$$
;

with tbl as (select parse_json(t.$1) mycol from values ('{"IntervaTime": [
    {
      "FromActivity": "FirstDoorOpened",
      "Goal": "2",
      "Order": "1",
      "ToActivity": "LastDoorOpened"
    },
    {
      "FromActivity": "FirstCustomerEntered",
      "Order": "2",
      "ToActivity": "LastCustomerEntered"
    },
    {
      "FromActivity": "FirstEmployeClockedIn",
      "Goal": "9",
      "Order": "3",
      "ToActivity": "LastEmployeClockedIn"
    }
]}') t)

select
  get_interval(mycol['IntervaTime'], 'FirstDoorOpened') FirstDoorOpened,
  get_interval(mycol['IntervaTime'], 'FirstCustomerEntered') FirstCustomerEntered,
  get_interval(mycol['IntervaTime'], 'FirstEmployeClockedIn') FirstEmployeClockedIn
from tbl;

* Я сделал некоторые предположения, поэтому предположим, что я понял их правильно.

...