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 ответов

24 просмотра

Аккуратно написать [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=#

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

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

Какой-то там пердун в 90-х решил, что есть какая-то разная типизация. Кого вообще это волнует?
КТ315
49
void terminal_scroll() { memmove(terminal_buffer, terminal_buffer + VGA_WIDTH, buffer_size - VGA_WIDTH); memset(terminal_buffer + buffer_size - VGA_WIDTH, 0, VGA_WIDTH); ...
Егор
47
Всем привет! Подскажите, пожалуйста, в чем ошибка? Настраиваю подключение к MySQL. Либы лежат рядом с exe. Все как по "учебнику"
Евгений
16
А можете как-то проверить меня по знаниям по ассемблеру?
A A
132
Здравствуйте! У меня появилась возможность купить книгу "Изучай Haskell во имя добра!". Но я где-то слышал, что эта книга устарела. Насколько это правда??
E
22
Здравствуйте! Я вот на stepic решаю задачи на хаскеле https://stepik.org/lesson/8443/step/8?unit=1578 мой код import Data.List (isInfixOf) removing :: String -> [String] ->...
E
10
Камрады, кто тесно работал с vtv, хотел уточнить. Ширина column задаётся жёстко на этапе создания дерева или можно в рантайме ее менять программно (не мышкой)?
Ed Doc
10
да ладно ... что там неочевидного ? глянуть в исх-ки датасета и/или кверика чтобы понять в каком месте и как выполняется обращения к св-вам blablaSQL - минутное дело, даже е...
Сергей
7
Здесь для arm кто-нибудь кодит ?
Nothing
52
Всем привет, у меня есть сервер принимающий входящие HTTP подключения, как проверить, что подключение было через прокси или нет, есть какие то поля в заголовках по которым мо...
DS
8
Карта сайта