powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Интервалы дат
17 сообщений из 17, страница 1 из 1
Интервалы дат
    #39994236
kuvshinka_irka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день!

Есть таблица вида

num|date
1|10.02.2020
1|11.02.2020
2|11.02.2020
3|11.02.2020
3|12.02.2020
3|13.02.2020

Необходимо разбить на интервалы дат в формат

num|start_date|end_date
1|10.02.2020|11.02.2020
2|11.02.2020|11.02.2020
3|11.02.2020|13.02.2020

Подскажите пожалуйста как это можно сделать?
...
Рейтинг: 0 / 0
Интервалы дат
    #39994243
Guzya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Что-то такое
Код: sql
1.
2.
3.
select id, start_date, end_date from
(select tab1.id as id,least(tab1.dat,tab2.dat) as start_date, greatest(b1.dat,tab2.dat) as end_date
from table tab1 join table tab2 on tab1.id=tab2.id ) group by id, start_date, end_date;
...
Рейтинг: 0 / 0
Интервалы дат
    #39994269
Фотография OoCc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kuvshinka_irka
Добрый день!

Есть таблица вида

num|date
1|10.02.2020
1|11.02.2020
2|11.02.2020
3|11.02.2020
3|12.02.2020
3|13.02.2020

Необходимо разбить на интервалы дат в формат

num|start_date|end_date
1|10.02.2020|11.02.2020
2|11.02.2020|11.02.2020
3|11.02.2020|13.02.2020

Подскажите пожалуйста как это можно сделать?

чтобы выбрать из таблицы минимальные и максимальные значения с одинаковом ID можно воспользоваться
Код: sql
1.
where not exists
...
Рейтинг: 0 / 0
Интервалы дат
    #39994326
kuvshinka_irka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
OoCc,

Могут быть разрывные периоды, в этом сложность, например для num=3

num|date
1|10.02.2020
1|11.02.2020
2|11.02.2020
3|11.02.2020
3|12.02.2020
3|13.02.2020
3|22.02.2020

должно быть

num|start_date|end_date
1|10.02.2020|11.02.2020
2|11.02.2020|11.02.2020
3|11.02.2020|13.02.2020
3|22.02.2020|22.02.2020
...
Рейтинг: 0 / 0
Интервалы дат
    #39994332
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kuvshinka_irka,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
with t as (
  select 1 as num, '10.02.2020' as "date" union all
  select 1, '11.02.2020' union all
  select 2, '11.02.2020' union all
  select 3, '11.02.2020' union all
  select 3, '12.02.2020' union all
  select 3, '13.02.2020' union all
  select 3, '22.02.2020'),
tt as (
  select 
      *
      ,cast("date" as timestamp) -  row_number()over(partition by num order by "date") * interval '1 day' as inv
  from t)
select
	num
    ,min("date") as start_date
    ,max("date") as end_date
from tt  
group by 
	num
    ,inv
order by 1,2



numstart_dateend_date110.02.202011.02.2020211.02.202011.02.2020311.02.202013.02.2020322.02.202022.02.2020
...
Рейтинг: 0 / 0
Интервалы дат
    #39994335
Фотография OoCc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kuvshinka_irka
OoCc,

Могут быть разрывные периоды, в этом сложность, например для num=3

num|date
1|10.02.2020
1|11.02.2020
2|11.02.2020
3|11.02.2020
3|12.02.2020
3|13.02.2020
3|22.02.2020

должно быть

num|start_date|end_date
1|10.02.2020|11.02.2020
2|11.02.2020|11.02.2020
3|11.02.2020|13.02.2020
3|22.02.2020|22.02.2020

это две разные задачки, сначала нужно решить задачку разбивки на правильные интервалы.
...
Рейтинг: 0 / 0
Интервалы дат
    #39994374
old_joy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kuvshinka_irka
Добрый день!

Есть таблица вида

num|date
1|10.02.2020
1|11.02.2020
2|11.02.2020
3|11.02.2020
3|12.02.2020
3|13.02.2020

Необходимо разбить на интервалы дат в формат

num|start_date|end_date
1|10.02.2020|11.02.2020
2|11.02.2020|11.02.2020
3|11.02.2020|13.02.2020

Подскажите пожалуйста как это можно сделать?

Запрос в два этапа.
На первом этапе - with - к вашей таблице формируете третий столбец, чтобы на выходе получить примерно такое:
num|date|Признак
1|10.02.2020|1
1|11.02.2020|1
1|10.02.2020|2
1|11.02.2020|2
2|11.02.2020|1
3|11.02.2020|1
3|12.02.2020|1
3|13.02.2020|2
3|14.02.2020|2

На втором этапе соединяете две копии результата по num и Признак
...
Рейтинг: 0 / 0
Интервалы дат
    #39994457
Guzya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
with t as (
  select 1 as id, '10.02.2020' as "dat" union all
  select 1, '11.02.2020' union all
  select 2, '11.02.2020' union all
  select 3, '11.02.2020' union all
  select 3, '12.02.2020' union all
  select 3, '13.02.2020' union all
  select 3, '22.02.2020') select id, min(start_date), max(end_date) from
(select tab1.id as id,least(tab1.dat,tab2.dat) as start_date, greatest(tab1.dat,tab2.dat) as end_date
from t tab1 join t tab2 on tab1.id=tab2.id ) as foo group by id order by id;



idminmax 1 10.02.2020 11.02.2020 2 11.02.2020 11.02.2020 3 11.02.2020 22.02.2020
...
Рейтинг: 0 / 0
Интервалы дат
    #39994646
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Guzya
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
with t as (
  select 1 as id, '10.02.2020' as "dat" union all
  select 1, '11.02.2020' union all
  select 2, '11.02.2020' union all
  select 3, '11.02.2020' union all
  select 3, '12.02.2020' union all
  select 3, '13.02.2020' union all
  select 3, '22.02.2020') select id, min(start_date), max(end_date) from
(select tab1.id as id,least(tab1.dat,tab2.dat) as start_date, greatest(tab1.dat,tab2.dat) as end_date
from t tab1 join t tab2 on tab1.id=tab2.id ) as foo group by id order by id;




idminmax 1 10.02.2020 11.02.2020 2 11.02.2020 11.02.2020 3 11.02.2020 22.02.2020

а чем "это всё" отличается от обычного
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
with t as (
  select 1 as id, '10.02.2020' as "dat" union all
  select 1, '11.02.2020' union all
  select 2, '11.02.2020' union all
  select 3, '11.02.2020' union all
  select 3, '12.02.2020' union all
  select 3, '13.02.2020' union all
  select 3, '22.02.2020') 
select id, min(start_date), max(end_date) from t group by id order by id;


?

пс
то, что это (результат) не по ТЗ, даже не берем во внимание ...
...
Рейтинг: 0 / 0
Интервалы дат
    #39994659
Фотография OoCc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[quot court#22190595]
Guzya

[поскипано]
пс
то, что это (результат) не по ТЗ, даже не берем во внимание ...

Надо сказать что твой тоже с ошибкой. попробуй на моем наборе.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
with 
orig_log as (
    select 1 as num, '10.02.2020' as stamp union all
    select 1, '11.02.2020' 
    union all
    select 1, '12.02.2020' 
    union all
    select 2, '13.02.2020' 
    union all
    select 3, '13.02.2020' 
    union all
    select 3, '14.02.2020' 
    union all
    select 3, '15.02.2020' 
    union all
    select 3, '22.02.2020' 
    union all
    select 3, '26.02.2020' 
    ),
ext_log as (select  *, 
        case when row_number()over(partition by num order by stamp) & 1 = 1 then 'b' else 'e' end as value_type, 
        row_number()over(order by num) as row_id
from orig_log)
select b.num id, b.stamp as begin_interval, coalesce(e.stamp,b.stamp) as end_interval 
from ext_log b left outer join ext_log e on  b.num = e.num and b.row_id+1 = e.row_id
where b.value_type = 'b'
order by b.stamp, b.num



id begin_interval end_interval110.02.202011.02.2020112.02.202012.02.2020213.02.202013.02.2020313.02.202014.02.2020315.02.202022.02.2020326.02.202026.02.2020
...
Рейтинг: 0 / 0
Интервалы дат
    #39994694
Guzya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Guzya

пс
то, что это (результат) не по ТЗ, даже не берем во внимание ...


Почему не по тз, как я понял на каждый id\num один интервал с мин, макс датами.
...
Рейтинг: 0 / 0
Интервалы дат
    #39994695
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Guzya
Guzya

пс
то, что это (результат) не по ТЗ, даже не берем во внимание ...


Почему не по тз, как я понял на каждый id\num один интервал с мин, макс датами.


прочтите 3тье сообщение в треде ))
...
Рейтинг: 0 / 0
Интервалы дат
    #39994708
Guzya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Boguk
Guzya
пропущено...


Почему не по тз, как я понял на каждый id\num один интервал с мин, макс датами.


прочтите 3тье сообщение в треде ))


теперь вижу ))
...
Рейтинг: 0 / 0
Интервалы дат
    #39995177
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OoCc
Надо сказать что твой тоже с ошибкой. попробуй на моем наборе.

чойта ?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
with t as (
    select 1 as num, '10.02.2020' as "date" union all
    select 1, '11.02.2020' 
    union all
    select 1, '12.02.2020' 
    union all
    select 2, '13.02.2020' 
    union all
    select 3, '13.02.2020' 
    union all
    select 3, '14.02.2020' 
    union all
    select 3, '15.02.2020' 
    union all
    select 3, '22.02.2020' 
    union all
    select 3, '26.02.2020' 
    ),
tt as (
  select 
      *
      ,cast("date" as timestamp) -  row_number()over(partition by num order by "date") * interval '1 day' as inv
  from t)
select
	num
    ,min("date") as start_date
    ,max("date") as end_date
from tt  
group by 
	num
    ,inv
order by 1,2


numstart_dateend_date110.02.202012.02.2020213.02.202013.02.2020313.02.202015.02.2020322.02.202022.02.2020326.02.202026.02.2020
имхо, ты не совсем правильно понял задачу ТС
Ей нужно получить непрерывные интервалы. Т.е. все записи "дней", для которых есть "последующий день" объединить в один интервал, - одну запись "начало интервала - конец интервала".
Это частный случай задачи "объединение интервалов" (когда задаются интервалы (пересекающиеся/не пересекающиеся/вложенные/стыкующиеся), и их нужно объединить в непрерывные).
Тут - 12567851 красивый пример
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
with t as (
    select 1 as num, cast('10.02.2020' as timestamp) as "date" union all
    select 1, cast('11.02.2020' as timestamp) 
    union all
    select 1, cast('12.02.2020' as timestamp) 
    union all
    select 2, cast('13.02.2020' as timestamp) 
    union all
    select 3, cast('13.02.2020' as timestamp) 
    union all
    select 3, cast('14.02.2020' as timestamp) 
    union all
    select 3, cast('15.02.2020' as timestamp) 
    union all
    select 3, cast('22.02.2020' as timestamp) 
    union all
    select 3, cast('26.02.2020' as timestamp) 
    )
select v_begin.b_date, min(v_end.e_date) as e_date,
       v_begin.num
  from 
       ( -- Находим все начала диапазонов:
          select num, "date" as b_date
            from t s1
           where not exists (
                               select null
                                 from t s2
                                where s2."date" < s1."date"
                                  and s2."date" + interval '1 days' >= s1."date"
                                  and s1.num = s2.num
                            )
       ) v_begin
  join 
       ( -- Находим все кончала диапазонов:
          select num, "date" as e_date
            from t s1
           where not exists (
                               select null
                                 from t s2
                                where s2."date" + interval '1 days' > s1."date" + interval '1 days' 
                                  and s2."date" <= s1."date" + interval '1 days' 
                                  and s1.num = s2.num
                            )
       ) v_end
--
-- Сливаем начала с кончалами:
    on v_begin.b_date <= v_end.e_date
   and v_begin.num = v_end.num
 group by v_begin.b_date, v_begin.num
 order by v_begin.num, min(v_end.e_date)
...
Рейтинг: 0 / 0
Интервалы дат
    #39995190
Фотография crutchmaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,

Вопрос, а насколько всё это целесообразно, и почему бы не решать такие задачи императивно?
...
Рейтинг: 0 / 0
Интервалы дат
    #39995191
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
crutchmaster
court,

Вопрос, а насколько всё это целесообразно, и почему бы не решать такие задачи императивно?


Ответ просто - производительность
sql лем часто это получается сильно быстрее чем на pl/pgsql и тем более чем выкачивание всех данных на клиента и там разбор (данных то может быть очень много)...

ps: я бы все эти exists бы переделал на window functions (lag/lead) оно было бы сильно эффективнее и требовало бы 1 прохода по таблице.


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Интервалы дат
    #39995214
Фотография OoCc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,

Да, неправильно понял, в свое оправдание могу сказать что я об этом написал выше.

crutchmastercourt,

Вопрос, а насколько всё это целесообразно, и почему бы не решать такие задачи императивно?

сдается мне что это надуманная задачка ради задачки.
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Интервалы дат
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]