почему Snowflake меняет порядок значений JSON при преобразовании в плоский список? - PullRequest
0 голосов
/ 26 апреля 2019

У меня есть объекты JSON, хранящиеся в таблице, и я пытаюсь написать запрос для получения первого элемента из этого JSON.

Сценарий репликации

create table staging.par.test_json (id int, val varchar(2000)); 

insert into staging.par.test_json values (1, '{"list":[{"element":"Plumber"},{"element":"Craft"},{"element":"Plumbing"},{"element":"Electrics"},{"element":"Electrical"},{"element":"Tradesperson"},{"element":"Home services"},{"element":"Housekeepings"},{"element":"Electrical Goods"}]}');
insert into staging.par.test_json values (2,'
  {
    "list": [
      {
        "element": "Wholesale jeweler"
      },
      {
        "element": "Fashion"
      },
      {
        "element": "Industry"
      },
      {
        "element": "Jewelry store"
      },
      {
        "element": "Business service"
      },
      {
        "element": "Corporate office"
      }
    ]
  }');



with cte_get_cats AS
(
select id, 
       val as category_list 
       from staging.par.test_json
),
cats_parse AS
(
  select id,
         parse_json(category_list) as c
  from cte_get_cats
),
distinct_cats as
(
  select id,
         INDEX,
         UPPER(cast(value:element AS varchar)) As c
  from 
      cats_parse,
      LATERAL flatten(INPUT => c:"list")
  order by 1,2 
) ,
cat_array AS
    (
        SELECT  
            id,
            array_agg(DISTINCT c) AS sds_categories
        FROM
            distinct_cats
        GROUP BY 1
    ),
sds_cats AS
( 
         select id,
         cast(sds_categories[0] AS varchar) as sds_primary_category
         from cat_array
)
select * from sds_cats;

Значения: Категории

{"list":[{"element":"Plumber"},{"element":"Craft"},{"element":"Plumbing"},{"element":"Electrics"},{"element":"Electrical"},{"element":"Tradesperson"},{"element":"Home services"},{"element":"Housekeepings"},{"element":"Electrical Goods"}]}

Сведение его к списку дает мне

["Plumber","Craft","Plumbing","Electrics","Electrical","Tradesperson","Home services","Housekeepings","Electrical Goods"]

Проблема: Порядок не всегда одинаков.Снежинка, кажется, меняет порядок, иногда снежинка меняет порядок согласно алфавиту.Как я могу сделать это статичным.Я не хочу, чтобы заказ был изменен.

1 Ответ

0 голосов
/ 29 апреля 2019

Проблема в том, как вы используете ARRAY_AGG:

        array_agg(DISTINCT c) AS sds_categories

Задав его таким образом, Snowflake не получает указаний о том, как должно быть организовано содержимое массива. Вы должны не предполагать, что массивы будут создаваться в том же порядке, что и их входные записи - возможно, но это не гарантировано. Так что вы, вероятно, хотите сделать

        array_agg(DISTINCT c) within group (order by index) AS sds_categories

Но это не сработает, так как если вы используете DISTINCT c, значение index для каждого c неизвестно. Возможно, вам не нужен DISTINCT, тогда это будет работать

        array_agg(c) within group (order by index) AS sds_categories

Если вам нужен DISTINCT, вам нужно каким-то образом связать index с отличным значением c. Одним из способов является использование функции MIN на index на входе. Вот полный запрос

with cte_get_cats AS
(
select id, 
       val as category_list 
       from staging.par.test_json
),
cats_parse AS
(
  select id,
         parse_json(category_list) as c
  from cte_get_cats
),
distinct_cats as
(
  select id,
         MIN(INDEX) AS index,
         UPPER(cast(value:element AS varchar)) As c
  from 
      cats_parse,
      LATERAL flatten(INPUT => c:"list")
  group by 1,3 
) ,
cat_array AS
    (
        SELECT  
            id,
            array_agg(c) within group (order by index) AS sds_categories
        FROM
            distinct_cats
        GROUP BY 1
    ),
sds_cats AS
( 
         select id,
         cast(sds_categories[0] AS varchar) as sds_primary_category
         from cat_array
)
select * from cat_array;
...