Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Как обработать ряд дат без использования оконных функций? / 17 сообщений из 17, страница 1 из 1
06.07.2017, 20:20
    #39484103
X3 кто
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
Есть ряд дат с различными значениями статуса.

Например:

DT STATUS
01.02.2017 1
05.02.2017 2
07.02.2017 2
21.02.2017 3
24.02.2017 1
25.02.2017 3
28.02.2017 2
03.03.2017 1

Необходимо подсчитать общее количество дней для каждого из статусов.

В результате должно получиться следующее:

Для STATUS=1:
с 01.02.2017 по 04.02.2017: 4 дня
с 24.02.2017 по 24.02.2017: 1 день
с 03.03.2017 по 03.03.2017: 1 день
итого: 6 дней

Для STATUS=2:
с 05.02.2017 по 20.02.2017: 16 дней
с 28.02.2017 по 02.03.2017: 3 дня
итого: 19 дней

Для STATUS=3:
с 21.02.2017 по 23.02.2017: 3 дня
с 25.02.2017 по 27.02.2017: 3 дня
итого: 6 дней

Я вполне себе представляю, как это выполнить с помощью “оконных” функций.

А как это сделать без “оконных” функций?
Причём так, чтобы подошло для любой RDBMS.
...
Рейтинг: 0 / 0
06.07.2017, 20:25
    #39484105
--Eugene--
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
X3 ктоПричём так, чтобы подошло для любой RDBMS.а че тогда подался в етот топик? подруку подвернулся?
...
Рейтинг: 0 / 0
06.07.2017, 21:15
    #39484118
--Eugene--
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
на скорую руку
Код: plsql
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.
with x as (
	select date'2017-02-01' dt, 1 status from dual union all
	select date'2017-02-05', 2 from dual union all
	select date'2017-02-07', 2 from dual union all
	select date'2017-02-21', 3 from dual union all
	select date'2017-02-24', 1 from dual union all
	select date'2017-02-25', 3 from dual union all
	select date'2017-02-28', 2 from dual union all
	select date'2017-03-03', 1 from dual
),
whole_interval as (
	select min_dt + level - 1 dt
		from (select min(dt) min_dt, max(dt) max_dt from x)
		connect by min_dt + level - 1 <= max_dt
),
whole_interval_with_statuses as (
	select i.dt,
			(select status
				from (
					select x.status,
							x.dt
						from x
						where x.dt <= i.dt
						order by x.dt desc)
				where rownum = 1) status
		from whole_interval i
)
select count(1)
	from whole_interval_with_statuses i
	group by status

STATUSCOUNT(1)1621936
...
Рейтинг: 0 / 0
06.07.2017, 22:11
    #39484137
andreymx
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
--Eugene--,

коннект бай распространен еще менее, чем анатилика
...
Рейтинг: 0 / 0
06.07.2017, 22:34
    #39484140
--Eugene--
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
andreymxконнект бай распространен еще менее, чем анатиликаТС не сказал, что без коннект бая.
а про то, "чтобы подошло для любой RDBMS" - я ему кагбы сразу намекнул
...
Рейтинг: 0 / 0
06.07.2017, 22:59
    #39484145
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
Уж не знаю, насколько распространена арифметика дат.
И совсем не хотел бы гонять такое по реальной базе.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
with x as (
	select date'2017-02-01' dt, 1 status from dual union all
	select date'2017-02-05', 2 from dual union all
	select date'2017-02-07', 2 from dual union all
	select date'2017-02-21', 3 from dual union all
	select date'2017-02-24', 1 from dual union all
	select date'2017-02-25', 3 from dual union all
	select date'2017-02-28', 2 from dual union all
	select date'2017-03-03', 1 from dual
)
---------------------------------------------------------
select status, sum(days_in_status) as days_in_status
from(
select x1.status
     , coalesce(min(x2.dt), x1.dt+1) - x1.dt as days_in_status
  from x x1 left join x x2 on x1.dt<x2.dt
  group by x1.status, x1.dt
) group by status
order by status
...
Рейтинг: 0 / 0
07.07.2017, 09:21
    #39484226
stax..
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
X3 кто,

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
  1  with x as (
  2     select date'2017-02-01' dt, 1 status from dual union all
  3     select date'2017-02-05', 2 from dual union all
  4     select date'2017-02-07', 2 from dual union all
  5     select date'2017-02-21', 3 from dual union all
  6     select date'2017-02-24', 1 from dual union all
  7     select date'2017-02-25', 3 from dual union all
  8     select date'2017-02-28', 2 from dual union all
  9     select date'2017-03-03', 1 from dual
 10  )
 11  select status,
 12   sum(nvl(((select min(dt) from x x2 where x2.dt>x.dt)-dt),1)) cc
 13  from x
 14* group by status
SQL> /

    STATUS         CC
---------- ----------
         1          6
         2         19
         3          6



.....
stax
...
Рейтинг: 0 / 0
07.07.2017, 09:47
    #39484252
env
env
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
X3 ктоПричём так, чтобы подошло для любой RDBMS.
Операции с датами тоже должны быть "подходящими для любой RDBMS"?
...
Рейтинг: 0 / 0
07.07.2017, 11:22
    #39484352
rekrabbe
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select sum( coalesce( (next_dt - dt), 1) ) as qty,
  status
from 
(
  select status,
    dt,
    lead(dt) over(order by dt) as next_dt
  from x
)
group by status


Ради интереса, как еще можно аналитикой, с помощью keep например?
...
Рейтинг: 0 / 0
07.07.2017, 12:17
    #39484410
stax..
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
rekrabbe,
first/last value, nth_value

.....
stax
...
Рейтинг: 0 / 0
07.07.2017, 18:02
    #39484816
X3 кто
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
--Eugene--X3 ктоПричём так, чтобы подошло для любой RDBMS.а че тогда подался в етот топик? подруку подвернулся?

А разве есть раздел форума, посвященный языку SQL без привязки к конкретной RDBMS?
Кроме того, львиная доля моего общения с RDBMS посвящена именно ORACLE.
...
Рейтинг: 0 / 0
07.07.2017, 18:15
    #39484830
X3 кто
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
--Eugene--andreymxконнект бай распространен еще менее, чем анатиликаТС не сказал, что без коннект бая.
а про то, "чтобы подошло для любой RDBMS" - я ему кагбы сразу намекнул

Я начал с того, что решил эту задачу с помощью оконных функций.
А с меня потребовали использовать строго SQL92.
...
Рейтинг: 0 / 0
07.07.2017, 18:26
    #39484839
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
X3 ктоА с меня потребовали использовать строго SQL92.
Ну тогда:
1. Заводим табличку-календарь.
2. В порядке возрастания дат "с различными значениями статуса" проводим update календаря значением статуса по критерию CALENDAR.DT >= STATUS.DT
3. Повторяем ежедневно для значения статуса >=<текущая дата>.
4. select status, count(*) from calendar where dt <= <текущая дата> group by dt

Вариация: календарь ограничен сверху текущей датой.
Ежедневно в календарь добавляется копия последней (order by dt) записи календаря, помеченная текущей датой.
select status, count(*) from calendar group by dt
...
Рейтинг: 0 / 0
07.07.2017, 19:02
    #39484862
X3 кто
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
andrey_anonymousX3 ктоА с меня потребовали использовать строго SQL92.
Ну тогда:
1. Заводим табличку-календарь.
2. В порядке возрастания дат "с различными значениями статуса" проводим update календаря значением статуса по критерию CALENDAR.DT >= STATUS.DT
3. Повторяем ежедневно для значения статуса >=<текущая дата>.
4. select status, count(*) from calendar where dt <= <текущая дата> group by dt

Вариация: календарь ограничен сверху текущей датой.
Ежедневно в календарь добавляется копия последней (order by dt) записи календаря, помеченная текущей датой.
select status, count(*) from calendar group by dt

А неплохой подход.
Благодарю.
...
Рейтинг: 0 / 0
08.07.2017, 10:04
    #39485008
coborhc
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
X3 кто,

тогда еще проще хранить в исходной таблице кроме даты изменения статуса еще дату след. изменения.
...
Рейтинг: 0 / 0
08.07.2017, 12:27
    #39485039
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
coborhcтогда еще проще хранить в исходной таблице кроме даты изменения статуса еще дату след. изменения.Это избыточность данных. Сиречь противоречивость.
...
Рейтинг: 0 / 0
10.07.2017, 12:28
    #39485667
stax..
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как обработать ряд дат без использования оконных функций?
Eliccoborhcтогда еще проще хранить в исходной таблице кроме даты изменения статуса еще дату след. изменения.Это избыточность данных. Сиречь противоречивость.
иногда избыточность полезна
напр непрерывный диапазон, достаточно даты действует с,
но удобно c избыточностью дата_по=LEAD(dat_from)-"1"

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


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