powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Интервальное хранение (пакуем каждодневные записи в отрезки)
12 сообщений из 12, страница 1 из 1
Интервальное хранение (пакуем каждодневные записи в отрезки)
    #39362449
DIMANNNNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Коллеги, здравствуйте.

Есть информация по балансам карт за каждый день.
И есть возможность существенно уменьшить её размер.
Пытаюсь упаковать данные интервально (исключая лишние строки с датами, в которые балансы повторяются).

Например для карты а история балансов такая:
автор07.07.2016 1к руб
08.07.2016 2к руб
09.07.2016 3к руб
10.07.2016 3к руб
11.07.2016 3к руб

Эти 5 записей можно урезать до 3:
автор07.07.2016 - 07.07.2016 1к руб
08.07.2016 - 08.07.2016 2к руб
09.07.2016 - 11.07.2016 3к руб

Код: 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.
31.
32.
33.
34.
35.
36.
create table shch_tmptmp
(card_id varchar(1),
as_of_date_b  date,
as_of_date_e  date,
balance_own_amt number);

----порция 1
INSERT INTO shch_tmptmp(card_id, as_of_date_b, as_of_date_e, balance_own_amt)
      VALUES('a',  '07.07.2016',  '07.07.2016',  1);
INSERT INTO shch_tmptmp(card_id, as_of_date_b, as_of_date_e, balance_own_amt)
      VALUES(
'b',  '07.07.2016',  '07.07.2016',    20);
INSERT INTO shch_tmptmp(card_id, as_of_date_b, as_of_date_e, balance_own_amt)
      VALUES(
'a',  '08.07.2016',  '08.07.2016',  2);
INSERT INTO shch_tmptmp(card_id, as_of_date_b, as_of_date_e, balance_own_amt)
      VALUES(
'b',  '08.07.2016',  '08.07.2016',    20);
INSERT INTO shch_tmptmp(card_id, as_of_date_b, as_of_date_e, balance_own_amt)
      VALUES(
'a',  '09.07.2016',  '09.07.2016',    3);
INSERT INTO shch_tmptmp(card_id, as_of_date_b, as_of_date_e, balance_own_amt)
      VALUES(
'b',  '09.07.2016',  '09.07.2016',    30);
INSERT INTO shch_tmptmp(card_id, as_of_date_b, as_of_date_e, balance_own_amt)
      VALUES(
'a',  '10.07.2016',  '10.07.2016',    3);
INSERT INTO shch_tmptmp(card_id, as_of_date_b, as_of_date_e, balance_own_amt)
      VALUES(
'b',  '10.07.2016',  '10.07.2016',    30);
INSERT INTO shch_tmptmp(card_id, as_of_date_b, as_of_date_e, balance_own_amt)
      VALUES(
'a',  '11.07.2016',  '11.07.2016',    3);
INSERT INTO shch_tmptmp(card_id, as_of_date_b, as_of_date_e, balance_own_amt)
      VALUES(
'b',  '11.07.2016',  '11.07.2016',    45);



Пишу код:
Код: 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.
select * from
(
--------суммы-одиночки (меняющиеся на следующий день)
      select  a.*,b.rating2,dat_e from
      (
          (SELECT card_id,as_of_date_b DAT_B, balance_own_amt,
              row_number() OVER (partition by card_id,balance_own_amt order by card_id,as_of_date_b)  AS rating--,
          FROM shch_tmptmp order by card_id,as_of_date_b) a
      ,
           (SELECT card_id, as_of_date_b DAT_E, balance_own_amt,
              row_number() OVER (partition by card_id,balance_own_amt order by card_id,as_of_date_b DESC)  AS rating2
          FROM shch_tmptmp order by card_id,as_of_date_b deSc) b
      where a.card_id=b.card_id and a.dat_b=b.dat_e and a.balance_own_amt=b.balance_own_amt
      and (RATING=1 and RATING2=1)
      order by A.card_id,A.dat_b
      )
)
union all
--------суммы-сплошняки (одинаковые несколько НЕПРЕРЫВНЫХ дней)
(
SELECT  CARD_ID,DAT_B,BALANCE_OWN_AMT,DAT_E from
(
    SELECT CARD_ID,DAT_B,rating,BALANCE_OWN_AMT,LEAD(DAT_E) OVER (ORDER BY CARD_ID,DAT_B) AS DAT_E FROM
    (
      select a.*,b.rating RATING2,DAT_E from  
      (SELECT card_id,as_of_date_b DAT_B, balance_own_amt,
              row_number() OVER (partition by card_id,balance_own_amt order by as_of_date_b)  AS rating--,
          FROM shch_tmptmp order by card_id,as_of_date_b) a
      left join
      (SELECT card_id, as_of_date_b DAT_E, balance_own_amt,
              row_number() OVER (partition by card_id,balance_own_amt order by as_of_date_b DESC)  AS rating
          FROM shch_tmptmp order by card_id,as_of_date_b deSc) b
      on a.card_id=b.card_id and a.dat_b=b.dat_e and a.balance_own_amt=b.balance_own_amt
      order by A.card_id,A.dat_b
    ) aa
          WHERE (RATING=1 OR RATING2=1) AND RATING+RATING2!=2
) aaa
where aaa.RATING=1
);


Все работает.

Только вот, когда добавляю
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
----порция 2
INSERT INTO shch_tmptmp(card_id, as_of_date_b, as_of_date_e, balance_own_amt)
      VALUES(
'a',  '12.07.2016',  '12.07.2016',    3);
INSERT INTO shch_tmptmp(card_id, as_of_date_b, as_of_date_e, balance_own_amt)
      VALUES(
'a',  '06.07.2016',  '06.07.2016',    2);
INSERT INTO shch_tmptmp(card_id, as_of_date_b, as_of_date_e, balance_own_amt)
      VALUES(
'a',  '20.07.2016',  '20.07.2016',    2);


начинаются аномалии:
Например для карты а история балансов такая:
автор06.07.2016 2к руб
07.07.2016 1к руб
08.07.2016 2к руб
09.07.2016 3к руб
10.07.2016 3к руб
11.07.2016 3к руб
20.07.2016 2к руб

Все балансы с 2к руб у карты а считаются за одну партицию. И в итоге получаем, что баланс 2к на всём отрезке 06.07.2016-20.07.2016.

А по-хорошему это должно разбиться на 3 куска:
автор06.07.2016 - 06.07.2016 2к руб
08.07.2016 - 08.07.2016 2к руб
20.07.2016 - 20.07.2016 3к руб
Эти косяки в принципе и логичны, только не знаю, как их обойти.

Заранее спасибо всем.
...
Рейтинг: 0 / 0
Интервальное хранение (пакуем каждодневные записи в отрезки)
    #39362457
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DIMANNNNN,

stff start_of_group
...
Рейтинг: 0 / 0
Интервальное хранение (пакуем каждодневные записи в отрезки)
    #39362806
DIMANNNNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
env, а что Ваша запись значит?
...
Рейтинг: 0 / 0
Интервальное хранение (пакуем каждодневные записи в отрезки)
    #39362815
DIMANNNNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DIMANNNNNenv, а что Ваша запись значит?
сам понял. спасибо
...
Рейтинг: 0 / 0
Интервальное хранение (пакуем каждодневные записи в отрезки)
    #39362874
DIMANNNNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Адаптировал под свой случай.

Может кому и пригодится.

авторnpp=as_of_date, user_id=card_id, doc_spec_id=balance_own_amt

Код: 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.
 with tab
     as (select 1 doc_spec_id,'a' user_id, to_date('01.02.2016') npp from dual
         union all
         select 2 doc_spec_id, 'a' user_id, to_date('02.02.2016') npp from dual
         union all
         select  2 doc_spec_id, 'a' user_id, to_date('03.02.2016') npp from dual
         union all
         select 2 doc_spec_id, 'a' user_id, to_date('04.02.2016') npp from dual
         union all
         select  1 doc_spec_id, 'a' user_id, to_date('05.02.2016') npp from dual
         union all
         select 1 doc_spec_id, 'a' user_id, to_date('06.02.2016') npp from dual
         union all
         select 3 doc_spec_id, 'a' user_id, to_date('07.02.2016') npp from dual
         
         union all
         select 3 doc_spec_id, 'b' user_id, to_date('03.02.2016') npp from dual
         union all
         select 1 doc_spec_id, 'b' user_id, to_date('04.02.2016') npp from dual
         union all
         select 5 doc_spec_id, 'b' user_id, to_date('05.02.2016') npp from dual
         union all
         select 5 doc_spec_id, 'b' user_id, to_date('06.02.2016') npp from dual
         union all
         select 1 doc_spec_id, 'b' user_id, to_date('07.02.2016') npp from dual
         union all
         select 1 doc_spec_id, 'b' user_id, to_date('17.02.2016') npp from dual
         union all
         select 5 doc_spec_id, 'b' user_id, to_date('27.02.2016') npp from dual)

select user_id,doc_spec_id, min(npp) npp_from, max(npp) npp_to
  from (
         select t.*, row_number() over(partition by user_id, doc_spec_id order by npp) - 
          to_number(to_char(npp, 'yyyy-mm-dd'), '9999G99G99', 'nls_numeric_characters=,-')
          as grp_id
           from tab t
       )
  group by user_id,doc_spec_id,grp_id
  order by min(npp);
...
Рейтинг: 0 / 0
Интервальное хранение (пакуем каждодневные записи в отрезки)
    #39362894
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DIMANNNNNАдаптировал под свой случай.
Может кому и пригодится.Ни в коем случае.
DIMANNNNN
Код: sql
1.
to_date('01.02.2016')

NLS-дерьмо.
DIMANNNNN
Код: sql
1.
2.
3.
 row_number() over(partition by user_id, doc_spec_id order by npp) - 
          to_number(to_char(npp, 'yyyy-mm-dd'), '9999G99G99', 'nls_numeric_characters=,-')
          as grp_id

Не используй трюкаческие приёмы, если не понимаешь на чём они основаны. А используй явно формулируемый start_of_group, в котором сложнее ошибиться.
Добавь следующие данные и помедитируй над результатом:
Код: plsql
1.
2.
3.
  union all select 5 doc_spec_id, 'b' user_id, date '2016-02-28' npp from dual
  union all select 5 doc_spec_id, 'b' user_id, date '2016-02-29' npp from dual
  union all select 5 doc_spec_id, 'b' user_id, date '2016-03-01' npp from dual

Существует множество способов превратить дату в монотонное число. Но некоторые щемятся ославиться со своим немонотонным.
...
Рейтинг: 0 / 0
Интервальное хранение (пакуем каждодневные записи в отрезки)
    #39363196
XMLer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ElicСуществует множество способов превратить дату в монотонное число.
Наш скоростной экспресс Урюпинск-Урюпинск следует без остановок
...
Рейтинг: 0 / 0
Интервальное хранение (пакуем каждодневные записи в отрезки)
    #39363237
DIMANNNNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Elic, ох, вижу.

Косячок. А как же быть?
...
Рейтинг: 0 / 0
Интервальное хранение (пакуем каждодневные записи в отрезки)
    #39363239
DIMANNNNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Elic[/src]Существует множество способов превратить дату в монотонное число. Но некоторые щемятся ославиться со своим немонотонным.
Теперь понял про монотонность. Нет, я как раз хотел бы узнать, как сделать это всё немонотонным.
...
Рейтинг: 0 / 0
Интервальное хранение (пакуем каждодневные записи в отрезки)
    #39363241
DIMANNNNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DIMANNNNNElic[/src]Существует множество способов превратить дату в монотонное число. Но некоторые щемятся ославиться со своим немонотонным.
Теперь понял про монотонность. Нет, я как раз хотел бы узнать, как сделать это всё немонотонным.
Точнее монотонным)
...
Рейтинг: 0 / 0
Интервальное хранение (пакуем каждодневные записи в отрезки)
    #39363252
DIMANNNNN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Elic, во
Поправил)
Код: 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.
with tab
     as (select 1 doc_spec_id,'a' user_id, to_date('01.02.2016')-1 npp from dual
         union all
         select 2 doc_spec_id, 'a' user_id, to_date('02.02.2016') npp from dual
         union all
         select  2 doc_spec_id, 'a' user_id, to_date('03.02.2016') npp from dual
         union all
         select 2 doc_spec_id, 'a' user_id, to_date('04.02.2016') npp from dual
         union all
         select  1 doc_spec_id, 'a' user_id, to_date('05.02.2016') npp from dual
         union all
         select 1 doc_spec_id, 'a' user_id, to_date('06.02.2016') npp from dual
         union all
         select 3 doc_spec_id, 'a' user_id, to_date('07.02.2016') npp from dual
         
         union all
         select 3 doc_spec_id, 'b' user_id, to_date('03.02.2016') npp from dual
         union all
         select 1 doc_spec_id, 'b' user_id, to_date('04.02.2016') npp from dual
         union all
         select 5 doc_spec_id, 'b' user_id, to_date('05.02.2016') npp from dual
         union all
         select 5 doc_spec_id, 'b' user_id, to_date('06.02.2016') npp from dual
         union all
         select 1 doc_spec_id, 'b' user_id, to_date('07.02.2016') npp from dual
         union all
         select 1 doc_spec_id, 'b' user_id, to_date('17.02.2016') npp from dual
         union all
         select 5 doc_spec_id, 'b' user_id, to_date('27.02.2016') npp from dual
union all select 5 doc_spec_id, 'b' user_id, to_date('28.02.2016') npp from dual
  union all select 5 doc_spec_id, 'b' user_id,to_date('29.02.2016') npp from dual
  union all select 5 doc_spec_id, 'b' user_id, to_date('01.03.2016') npp from dual
    union all select 5 doc_spec_id, 'b' user_id, to_date('02.03.2016') npp from dual)
         
  
select user_id,doc_spec_id, min(npp) npp_from, max(npp) npp_to
  from (
         select t.*, row_number() over(partition by user_id, doc_spec_id order by npp) - 
         to_number(to_char(npp,'J'))
          as grp_id
           from tab t
       )
  group by user_id,doc_spec_id,grp_id
  order by min(npp);
...
Рейтинг: 0 / 0
Интервальное хранение (пакуем каждодневные записи в отрезки)
    #39363308
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DIMANNNNNПоправил.
Код: sql
1.
to_date('02.03.2016')

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


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