172 похожих чатов

Подскажите пожалуйста Есть 2 таблицы Client_id Start_dt End_dt Client_addr


123 1900-01-01 2012-07-04 Улица Строителей 5
123 2012-07-05 2015-03-01 Ленинградский проспект, 21
123 2015-03-02 9999-12-31 Мосфильмовская ул, 12
… … … …


Client_id Start_dt End_dt Client_job
123 1900-01-01 2007-02-11 ПАО Аэрофлот
123 2007-02-12 2013-11-22 ПАО ВТБ
123 2015-03-02 9999-12-31 Мосфильмовская ул, 12
… … … …

Их надо объединить так, чтоб получилась такая таблица
Client_id Start_dt End_dt Client_addr Client_job
123 1900-01-01 2007-02-11 Улица Строителей 5 ПАО Аэрофлот
123 2007-02-12 2012-07-04 Улица Строителей 5 ПАО ВТБ
123 2012-07-05 2013-11-22 Ленинградский проспект, 21 ПАО ВТБ
… … … … …

Т.е. учитывая временной диапазон, как к этому можно подступиться?

15 ответов

28 просмотров

Аккуратно написать [FULL] JOIN? Или здесь есть что-то, чего я не вижу?

там просто надо пересечение интервалов дат, кроме связи по client_id

Ну да, аккуратно записать это пересечение и выражения для start, end в результате, и всё... нет?

ну дальше только автор может ответить. по идее всё

Yaroslav Schekin
Ну да, аккуратно записать это пересечение и выраже...

Вот не совсем понятно как записать пересечение и выражения для start и end 🤔

Александр Витковский
Вот не совсем понятно как записать пересечение и в...

Пересечение отрезков числовой прямой проходят на... геометрии в 7 классе, кажется? ;) Выражения записываются аналогично.

Александр Витковский
Вот не совсем понятно как записать пересечение и в...

Хотя подождите. Это же зависит от того, какой результат Вам нужен — может, это вообще не на пересечения задача.

А тут разве не так: Либо начало одного диапазона входит в другой либо конец? Вроде так должно получится… on client_id1 = client_id2 and (start1 between start2 and end2 or end1 between start2 and end2)

Roman Lukianov
А тут разве не так: Либо начало одного диапазона ...

(Прочитал исходный вопрос внимательнее) Да вот неизвестно, в чём тут задача, и даже непонятно, что значат исходные данные, мне кажется.

Yaroslav Schekin
(Прочитал исходный вопрос внимательнее) Да вот неи...

ну как я понял, необходимо определить какой адрес какой организации в какой период времени принадлежал, а там кто знает )))

Roman Lukianov
ну как я понял, необходимо определить какой адрес ...

Там две таблицы. И вторая, судя по всему, про Client_job, но в этом поле есть и значение "Мосфильмовская ул, 12". ;) Кроме того, непонятно, бывают ли разрывы в данных (когда у клиента нет адреса или работы), а если нет — то зачем там два поля с датами. В общем, это у автора нужно спрашивать...

Roman Lukianov
ну как я понял, необходимо определить какой адрес ...

Спасибо, таким запросом проблема решилась) select a.client_id, case when a.start_dt between j.start_dt and j.end_dt then a.start_dt else j.start_dt end start_dt, case when a.end_dt between j.start_dt and j.end_dt then a.end_dt else j.end_dt end start_dt, client_addr, client_job from temp.t_client_addr a join temp.t_client_job j on a.client_id = j.client_id and (a.start_dt between j.start_dt and j.end_dt or a.end_dt between j.start_dt and j.end_dt)

Как-то так: postgres=# create table addr (id int, start_dt date, end_dt date, addr text); CREATE TABLE postgres=# create table job (id int, start_dt date, end_dt date, job text); postgres=# insert into addr values (123, '1900-01-01', '2012-07-04', 'Улица Строителей 5'), (123, '2012-07-05', '2015-03-01', ' Ленинградский проспект, 21'), (123, '2015-03-02', '9999-12-31', 'Мосфильмовская ул, 12'); INSERT 0 3 postgres=# insert into job values (123, '1900-01-01', '2007-02-11', 'ПАО Аэрофлот'), (123, '2007-02-12', '2013-11-22', 'ПАО ВТБ'), (123, '2013-11-23', '9999-12-31', 'Роскосмос'); INSERT 0 3 postgres=# select addr.id, GREATEST(addr.start_dt, job.start_dt) as start_dt, LEAST(addr.end_dt, job.end_dt) as end_dt, addr, job from addr join job on addr.id = job.id and GREATEST(addr.start_dt, job.start_dt) < LEAST(addr.end_dt, job.end_dt) order by start_dt; id | start_dt | end_dt | addr | job -----+------------+------------+-----------------------------+-------------- 123 | 1900-01-01 | 2007-02-11 | Улица Строителей 5 | ПАО Аэрофлот 123 | 2007-02-12 | 2012-07-04 | Улица Строителей 5 | ПАО ВТБ 123 | 2012-07-05 | 2013-11-22 | Ленинградский проспект, 21 | ПАО ВТБ 123 | 2013-11-23 | 2015-03-01 | Ленинградский проспект, 21 | Роскосмос 123 | 2015-03-02 | 9999-12-31 | Мосфильмовская ул, 12 | Роскосмос (5 rows) postgres=# Но это, если разрывов нет. Если разрывы есть, то .... как-будто бы asof join подошёл, которого нету в postgresql. Поэтому придётся эмулировать его оконными функциями.

Aleksey Stavrov
Как-то так: postgres=# create table addr (id int, ...

Интересное решение, спасибо)

Александр Витковский
Интересное решение, спасибо)

А вот решение с разрывами (только для работы, для адреса можно сделать аналогично): postgres=# insert into addr values (123, '1900-01-01', '2012-07-04', 'Улица Строителей 5'), (123, '2012-07-05', '2015-03-01', ' Ленинградский проспект, 21'), (123, '2015-03-02', '9999-12-31', 'Мосфильмовская ул, 12'); INSERT 0 3 postgres=# insert into job values (123, '1900-01-01', '2007-02-11', 'ПАО Аэрофлот'), (123, '2007-02-28', '2013-11-22', 'ПАО ВТБ'), (123, '2015-11-17', '2017-12-31', 'Роскосмос'); INSERT 0 3 postgres=# with not_work as ( select * from ( select job.id, lag(end_dt, 1, '1970-01-01') over (partition by id order by start_dt) + 1 as start_dt, start_dt - 1 as end_dt, 'радовался жизни' as job from job ) as t where start_dt <= end_dt union all select job.id, max(end_dt) + 1 as start_dt, '9999-12-31' as end_dt, 'радовался жизни до её конца' as job from job group by job.id ), all_work as ( select * from not_work union all select * from job ) select addr.id, GREATEST(addr.start_dt, w.start_dt) as start_dt, LEAST(addr.end_dt, w.end_dt) as end_dt, addr, job from addr join all_work as w on addr.id = w.id and GREATEST(addr.start_dt, w.start_dt) < LEAST(addr.end_dt, w.end_dt) order by start_dt; id | start_dt | end_dt | addr | job -----+------------+------------+-----------------------------+----------------------------- 123 | 1900-01-01 | 2007-02-11 | Улица Строителей 5 | ПАО Аэрофлот 123 | 2007-02-12 | 2007-02-27 | Улица Строителей 5 | радовался жизни 123 | 2007-02-28 | 2012-07-04 | Улица Строителей 5 | ПАО ВТБ 123 | 2012-07-05 | 2013-11-22 | Ленинградский проспект, 21 | ПАО ВТБ 123 | 2013-11-23 | 2015-03-01 | Ленинградский проспект, 21 | радовался жизни 123 | 2015-03-02 | 2015-11-16 | Мосфильмовская ул, 12 | радовался жизни 123 | 2015-11-17 | 2017-12-31 | Мосфильмовская ул, 12 | Роскосмос 123 | 2018-01-01 | 9999-12-31 | Мосфильмовская ул, 12 | радовался жизни до её конца (8 rows) postgres=#

Похожие вопросы

Обсуждают сегодня

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Карта сайта