Как объединить две таблицы, чтобы определить диапазоны дат, когда одна таблица содержит (id, start_date), а другая содержит (id, end_date) - PullRequest
1 голос
/ 10 февраля 2020

Я новичок в SQL, надеюсь, вы, ребята, не найдете это глупым. Здесь мы работаем с двумя таблицами, одна из которых содержит даты начала, а другая - даты окончания. Записи не соответствуют последовательности / возможности дубликатов.

**TABLE 1**
id  start_date
1   2019-04-23
1   2019-06-05
1   2019-06-05
1   2019-10-29
1   2019-12-16
2   2019-01-05
3   2020-02-01

**TABLE 2**
id  end_date
1   2019-04-23
1   2019-06-05
1   2019-06-06
1   2019-06-06
1   2019-07-24
1   2019-10-16
2   2020-01-04

**EXPECTED OUTPUT**
id  start_date  end_date
1   2019-04-23  2019-06-05
1   2019-10-29  null
2   2019-01-05  2020-01-04
3   2020-02-01  null

Ответы [ 3 ]

1 голос
/ 10 февраля 2020

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

with table1 as (
      select 1 as id, date('2019-04-23') as start_date union all
      select 1,   '2019-06-05' union all
      select 1,   '2019-06-05' union all
      select 1,   '2019-10-29' union all
      select 1,   '2019-12-16' union all
      select 2,   '2019-01-05' union all
      select 3,   '2020-02-01'
     ),
     table2 as (
      SELECT 1 as id, DATE('2019-04-23') as end_date union all
      SELECT 1,   '2019-06-05' union all
      select 1,   '2019-06-06' union all
      select 1,   '2019-06-06' union all
      select 1,   '2019-07-24' union all
      select 1,   '2019-10-16' union all
      select 2,   '2020-01-04'
     ) 
select id, min(start_date), end_date
from (select id, start_date,
         first_value(end_date ignore nulls) over (partition by id order by DATE_DIFF(coalesce(start_date, end_date), CURRENT_DATE, day) RANGE between 1 following and unbounded following) as end_date
      from ((select id, start_date, null as end_date
             from table1
            ) union all
            (select id, null as start_date, end_date
             from table2
            )
           ) se
     )
group by id, end_date
having min(start_date) is not null;
0 голосов
/ 10 февраля 2020

Ниже для BigQuery Standard SQL

#standardSQL
SELECT id, start_date, IF(end_date = '9999-01-01', NULL, end_date) end_date
FROM (
  SELECT id, start_date, ARRAY_AGG(end_date ORDER BY end_date LIMIT 1)[OFFSET(0)] end_date
  FROM (
    SELECT id, start_date, IF(start_date < end_date, end_date, '9999-01-01')  end_date
    FROM `project.dataset.table1` 
    LEFT JOIN `project.dataset.table2`
    USING (id)
  )
  GROUP BY id, start_date
)

Если применить к образцу данных из вашего вопроса - результат будет

Row id  start_date  end_date     
1   1   2019-04-23  2019-06-05   
2   1   2019-06-05  2019-06-06   
3   1   2019-10-29  null     
4   1   2019-12-16  null     
5   2   2019-01-05  2020-01-04   
6   3   2020-02-01  null      

Примечание: быстро и не оптимизировано - но выглядит лайк дает желаемый результат

0 голосов
/ 10 февраля 2020

Почему у вас есть несколько записей с одинаковым идентификатором (я предполагаю, что идентификатор является первичным ключом)? Я предлагаю вам сделать идентификатор уникальным и создать ограничение внешнего ключа в таблице конечных дат (поскольку не может быть и конечной даты без начальной даты) и использовать отношение внешнего ключа для получения желаемых результатов. Например, SELECT S.start_date, E.end_date FROM table1 S JOIN table2 E, где S.id = E.table1_fk

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...