Улей: сгруппировать, используя функцию усреднения и функцию наибольшей частоты - PullRequest
2 голосов
/ 12 марта 2020

У меня есть структура таблицы, подобная этой

|---------------------|----------|-----------|
|    col_1            |  col_2   |   col_3   |
|---------------------|----------|-----------|
|  2018-01-15 17:56   | A        |   3       |
|---------------------|----------|-----------|
|  2018-01-15 17:56   | A        |   2       |
|---------------------|----------|-----------|
|  2018-10-23 23:43   | B        |   True    |
|---------------------|----------|-----------|
|  2018-10-23 23:43   | B        |   False   |
|---------------------|----------|-----------|
|  2018-10-23 23:43   | A        |    3      |
|---------------------|----------|-----------|
|  2018-10-23 23:43   | B        |    True   |
|---------------------|----------|-----------|

Я бы хотел сгруппировать по col_1 и взять среднее значение col_3, если col_2 - A, и принимать частое значение col_3 если col_2 - B. Желаемый результат будет

|---------------------|----------|-----------|
|    col_1            |  A       |   B       |
|---------------------|----------|-----------|
|  2018-01-15 17:56   | 2.5      |   Null    |
|---------------------|----------|-----------|
|  2018-10-23 23:43   | 3        |   True    |
|---------------------|----------|-----------|

Без функции частоты, когда col_2 - B, я знаю, что могу сделать что-то подобное

select col_1,
       avg(case when col_2='A' then col_3 end) as A
from my_table
group by col_1

Как добавить частотную функцию, когда col_2 - B?

Ответы [ 2 ]

1 голос
/ 12 марта 2020

Вы можете использовать два уровня агрегации:

select col1,
       (sum(case when col2 = 'A' then col3 * cnt end)/
        sum(case when col2 = 'A' then cnt end)
       ) as A,
       max(case when col2 = 'B' and seqnum = 1 then col3 end) as B
from (select col1, col2, col3, count(*) as cnt,
             row_number() over (partition by col1 order by count(*) desc) as seqnum
      from t
      group by col1, col2, col3
     ) t
group by col1;
0 голосов
/ 12 марта 2020

Используйте функции analyti c, см. Комментарии в коде:

with my_table as (
select stack(6,
'2018-01-15 17:56','A', '3'    ,
'2018-01-15 17:56','A', '2'    ,
'2018-10-23 23:43','B', 'True' ,
'2018-10-23 23:43','B', 'False',
'2018-10-23 23:43','A', '3'    ,
'2018-10-23 23:43','B', 'True' ) as (col_1 , col_2,  col_3)
)
select col_1, --final aggregation by col_1
       max(avg)           as A,
       max(most_frequent) as B
from(       
select col_1, col_2, col_3, cnt, --calculate avg and most_frequent
       case when col_2='A' then avg(col_3) over(partition by col_1, col_2) else null end as avg,
       case when col_2='B' then first_value(col_3) over(partition by col_1, col_2 order by cnt desc) else null end as most_frequent
  from
      (
      select  col_1, col_2, col_3, --calculate count
              case when col_2='B' then count(*) over(partition by col_1, col_2, col_3) else null end as cnt
        from my_table
      )s  
)s      
group by col_1      
;

Результат:

col_1                   a       b
2018-01-15 17:56        2.5     NULL
2018-10-23 23:43        3.0     True
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...