Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Интервалы дат / 17 сообщений из 17, страница 1 из 1
31.08.2020, 20:43
    #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
31.08.2020, 21:33
    #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
31.08.2020, 23:09
    #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
01.09.2020, 09:52
    #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
01.09.2020, 10:15
    #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
01.09.2020, 10:21
    #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
01.09.2020, 11:44
    #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
01.09.2020, 13:53
    #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
01.09.2020, 22:11
    #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
02.09.2020, 00:12
    #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
02.09.2020, 09:31
    #39994694
Guzya
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Интервалы дат
Guzya

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


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

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


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


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


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


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


теперь вижу ))
...
Рейтинг: 0 / 0
03.09.2020, 11:58
    #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
03.09.2020, 12:31
    #39995190
crutchmaster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Интервалы дат
court,

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

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


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

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


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

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

crutchmastercourt,

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

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


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