Оптимизация запросов Hive - PullRequest
1 голос
/ 03 октября 2019

Мое требование заключается в том, чтобы получить идентификатор и имя учащихся, имеющих более 1 идентификатора электронной почты, и ввести = 1.

Я использую запрос типа

select distinct b.id, b.name, b.email, b.type,a.cnt
from (
  select id, count(email) as cnt
  from (
    select distinct id, email
    from table1
  ) c
  group by id
) a
join table1 b on a.id = b.id
where b.type=1
order by b.id

Пожалуйста, дайте мнезнаю, что это штраф или любая более простая версия доступна.

Sample data is like:
id name email type 
123 AAA abc@xyz.com 1
123 AAA acd@xyz.com 1
123 AAA ayx@xyz.com 3
345 BBB nch@xyz.com 1
345 BBB nch@xyz.com 1
678 CCC iuy@xyz.com 1


Expected Output:
123 AAA abc@xyz.com 1 2
123 AAA acd@xyz.com 1 2
345 BBB nch@xyz.com 1 1
678 CCC iuy@xyz.com 1 1

Ответы [ 5 ]

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

Вы можете использовать group by -> having count() для этого требования.

select distinct b.id
    , b.name,
    , b.email
    , b.type 
from table1 b
where id in 
    (select distinct id from table1 group by email, id having count(email) > 1) 
and b.type=1 
order by b.id
0 голосов
/ 04 октября 2019

Это очень похоже на ваш запрос, но здесь я фильтрую данные на начальном этапе (во внутреннем запросе), чтобы объединение не происходило при меньшем количестве данных

 select distinct b.id,b.name,b.email,b.type,intr_table.cnt from table1 orig_table join 
    (
        select a.id,a.type,count(a.email) as cnt from table1 as a where a.type=1 group by a
    ) intr_table on inter_table.id=orig_table.id,inter_table.type=orig_table.type
0 голосов
/ 03 октября 2019

Еще один метод, использующий collect_set и принимающий размер возвращаемого массива для расчета отдельных писем.

Демонстрация:

--your data example
with table1 as ( --use your table instead of this 
  select stack(6,
    123, 'AAA', 'abc@xyz.com', 1,
    123, 'AAA', 'acd@xyz.com', 1,
    123, 'AAA', 'ayx@xyz.com', 3,
    345, 'BBB', 'nch@xyz.com', 1,
    345, 'BBB', 'nch@xyz.com', 1,
    678, 'CCC', 'iuy@xyz.com', 1
  ) as (id, name, email, type )
) 

--query   
select distinct id, name, email, type, 
       size(collect_set(email) over(partition by id)) cnt
  from table1
 where type=1

Результат:

id  name    email   type    cnt 
123 AAA  abc@xyz.com    1   2   
123 AAA  acd@xyz.com    1   2   
345 BBB  nch@xyz.com    1   1   
678 CCC  iuy@xyz.com    1   1   

Здесь нам все еще нужен DISTINCT, потому что аналитическая функция не удаляет дубликаты, как в случае 345 BBB nch@xyz.com.

0 голосов
/ 03 октября 2019

Я настоятельно рекомендую использовать оконные функции. Однако Hive не поддерживает count(distinct) как оконную функцию. Есть разные методы, чтобы решить эту проблему. Одним из них является сумма dense_rank() s:

select id, name, email, type, cnt
from (select t1.*,
             (dense_rank() over (partition by id order by email) +
              dense_rank() over (partition by id order by email desc)
             ) as cnt
      from table1 t1
     ) t
where type = 1;

Я ожидаю, что это будет иметь лучшую производительность, чем ваша версия. Однако стоит протестировать разные версии, чтобы увидеть, какая из них имеет лучшую производительность (и не стесняйтесь возвращаться, чтобы сообщить другим, какая из них лучше).

0 голосов
/ 03 октября 2019

Вы можете попробовать использовать аналитическую функцию count ():

SELECT sub.ID, sub.NAME
  FROM (SELECT ID, NAME, COUNT (*) OVER (PARTITION BY ID, EMAIL) cnt
          FROM raw.crddacia_raw) sub
 WHERE sub.cnt > 1 AND sub.TYPE = 1
...