Как я могу сгруппировать по столбцу дела, чем использует объект JSON? - PullRequest
1 голос
/ 07 октября 2019

Я пробовал следующее

select payload:col1 as col1
       , case
            when contains(payload:col2, 'aaa') then 'type1'
            else 'other'
         end as type
       , count(*) as c
  from table1
  group by col1, type
  ;

, где payload - это столбец JSON / object.

Это приводит к SQL compilation error: error line 3 at position 26 'table1.PAYLOAD' in select clause is neither an aggregate nor in the group by clause.

Насколько я понимаю, я должен быть в состоянии сгруппировать по столбцу дела type и payload на самом деле не в любом выходном столбце (естьслучай, который использует payload, но payload сам по себе не)

Ответы [ 2 ]

2 голосов
/ 07 октября 2019

В списке SELECT запроса GROUP BY вы можете ссылаться на «что угодно» внутри выражения агрегации, но только на выражения GROUP BY вне выражение агрегации.

В вашем случае, я считаю (не проверено), что вы не должны были получить ошибку, если GROUP BY содержал payload:col2 или contains(payload:col2, 'aaa') илиЦелое выражение типа столбца. Только последние два дали бы правильный результат, однако ...

Самое компактное GROUP BY выражение, которое будет работать, я думаю, будет:

GROUP BY col1, type, contains(payload:col2, 'aaa')

С этим ваш SELECT listвыражения только ссылки GROUP BY выражения из таблицы выражение запроса.

EDIT: слишком низкая репутация для комментария);

@ ecerulm Нет, я имел в виду целое"type" выражение столбца , то есть:

GROUP BY col1, type,
     case
        when contains(payload:col2, 'aaa') then 'type1'
        else 'other'
     end

Фактически объясняется, как именно это должно работать в стандарте SQL, поэтому сообщение об ошибке вы получитев соответствии со стандартом.

1 голос
/ 07 октября 2019

Скорее всего, причина в том, что есть столбец с тем же именем в исходной таблице . В вашем случае, если есть table1.type, тогда GROUP BY type с относится к table1.type, а не к вашему CASE....END as type.

В обычном случае вы можете ссылаться на CASE ... END as colname в предложении GROUP BY по псевдониму, без необходимости повторять CASE...END в GROUP BY. Например, следующие автономные примеры выполняются без проблем:

create or replace temporary table table1 as (
    select parse_json(column1) as payload from values
         ('{"col1": 1, "col2": "aaa"}')
        ,('{"col1": 1, "col2": "aaa"}')
        ,('{"col1": 2, "col2": "aaa"}')
        ,('{"col1": 2, "col2": "bbb"}')
);
select
    payload:col1 as col1
    ,case
     when payload:col2 = 'aaa' then 'type1'
     else 'other'
    end as type
    ,count(*) as c
from table1
group by col1, type;

-- result:
COL1    TYPE    C
1   type1   2
2   type1   1
2   other   1

Это показывает, что вы можете GROUP BY xxx, где xxx - это псевдоним столбца case, который использует оператор двоеточия для объекта JSON.

Также вы всегда можете использовать CTE в качестве обходного пути:

with t1 as (
  select payload:col1 as col1
       , case
            when contains(payload:col2, 'aaa') then 'type1'
            else 'other'
         end as type
  from table1
)
select col1
       ,type
       ,count(*) as c 
  group by col1, type
  ;

В этом случае, если есть table.type, который не виден в последнем выборе, поэтому group by type относится кt1.type а не table1.type.

...