Как отфильтровать повторяющиеся / повторяющиеся поля в bigquery? - PullRequest
0 голосов
/ 04 августа 2020

У меня есть таблица без primaryKey. И я пытаюсь получить события самой ранней даты, сгруппированные по идентификатору.

Вот как выглядит небольшой фрагмент моей таблицы:

|----------|------------------|-------------|
|    id    |       date       |    events   |
|----------|------------------|-------------|
|     1    |2020-04-11 3:44:20|     call    |
|----------|------------------|-------------|
|     3    |2020-04-21 7:59:06| appointment |
|----------|------------------|-------------|
|     1    |2020-04-17 1:14:32| appointment |
|----------|------------------|-------------|
|     2    |2020-04-10 3:41:17|   feedback  |
|----------|------------------|-------------|
|     1    |2020-04-23 1:36:13| appointment |
|----------|------------------|-------------|
|     3    |2020-04-12 4:55:38|     call    |
|----------|------------------|-------------|

Это результат, который я ищу:

|----------|------------------|-------------|
|    id    |       date       |    events   |
|----------|------------------|-------------|
|     1    |2020-04-11 3:44:20|     call    |
|----------|------------------|-------------|
|     2    |2020-04-10 3:41:17|   feedback  |
|----------|------------------|-------------|
|     3    |2020-04-12 4:55:38|     call    |
|----------|------------------|-------------|

Я пытаюсь получить события по идентификатору только для их соответствующей MIN (даты), но проблема в том, что мне нужно выбрать события SELECT, но затем мне нужно добавить события в GROUP BY, поэтому я не могу GROUP BY id только так, как хотелось бы. Я перепробовал много разных версий, но вот одна:

SELECT id, MIN(date), events
FROM mydataset.mytable
GROUP BY id, events

Имейте в виду, что моя таблица намного больше этой. Любая помощь будет очень признательна.

Ответы [ 4 ]

1 голос
/ 04 августа 2020

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

select array_agg(t order by date asc limit 1)[ordinal(1)].*
from mydataset.mytable t
group by t.id;

Или более традиционный метод использования row_number():

select t.* except (seqnum)
from (select t.*, row_number() over (partition by id order by date) as seqnum
      from mydataset.mytable t
     ) t
where seqnum = 1;
0 голосов
/ 05 августа 2020

на основе ответа Гордона с комментарием Джонса -

Версия ниже не требует использования псевдонима и позволяет использовать только id в GROUP BY

#standardSQL
SELECT AS VALUE ARRAY_AGG(t ORDER BY date LIMIT 1)[ORDINAL(1)]
FROM `project.dataset.table` t
GROUP BY id
0 голосов
/ 05 августа 2020

Соединение с производной таблицей может работать лучше, особенно. если идентификатор и дата проиндексированы:

select m.*
 from mytable m
  join (select id, min(date) date
    from mytable
    group by id ) x
   on m.id = x.id
    and m.date = x.date
;
0 голосов
/ 04 августа 2020

Вы можете изменить то, что у вас есть, как uncorrelated подзапрос

select *
from mytable 
where (id, date) in (select id, min(date)
                     from mytable
                     group by id);

Если ваша БД поддерживает window functions, вы также можете сделать

select distinct id, 
                min(date) over(partition by id) date,
                first_value(events) over (partition by id order by date asc) events
from mytable;

Выходы

+----+---------------------+----------+
| id |        date         |  events  |
+----+---------------------+----------+
|  1 | 2020-04-11 03:44:20 | call     |
|  2 | 2020-04-10 03:41:17 | feedback |
|  3 | 2020-04-12 04:55:38 | call     |
+----+---------------------+----------+
...