Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Интервальное хранение (пакуем каждодневные записи в отрезки) / 12 сообщений из 12, страница 1 из 1
08.12.2016, 12:18
    #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
08.12.2016, 12:26
    #39362457
env
env
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Интервальное хранение (пакуем каждодневные записи в отрезки)
DIMANNNNN,

stff start_of_group
...
Рейтинг: 0 / 0
08.12.2016, 17:16
    #39362806
DIMANNNNN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Интервальное хранение (пакуем каждодневные записи в отрезки)
env, а что Ваша запись значит?
...
Рейтинг: 0 / 0
08.12.2016, 17:19
    #39362815
DIMANNNNN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Интервальное хранение (пакуем каждодневные записи в отрезки)
DIMANNNNNenv, а что Ваша запись значит?
сам понял. спасибо
...
Рейтинг: 0 / 0
08.12.2016, 18:16
    #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
08.12.2016, 18:42
    #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
09.12.2016, 10:37
    #39363196
XMLer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Интервальное хранение (пакуем каждодневные записи в отрезки)
ElicСуществует множество способов превратить дату в монотонное число.
Наш скоростной экспресс Урюпинск-Урюпинск следует без остановок
...
Рейтинг: 0 / 0
09.12.2016, 11:21
    #39363237
DIMANNNNN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Интервальное хранение (пакуем каждодневные записи в отрезки)
Elic, ох, вижу.

Косячок. А как же быть?
...
Рейтинг: 0 / 0
09.12.2016, 11:23
    #39363239
DIMANNNNN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Интервальное хранение (пакуем каждодневные записи в отрезки)
Elic[/src]Существует множество способов превратить дату в монотонное число. Но некоторые щемятся ославиться со своим немонотонным.
Теперь понял про монотонность. Нет, я как раз хотел бы узнать, как сделать это всё немонотонным.
...
Рейтинг: 0 / 0
09.12.2016, 11:24
    #39363241
DIMANNNNN
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Интервальное хранение (пакуем каждодневные записи в отрезки)
DIMANNNNNElic[/src]Существует множество способов превратить дату в монотонное число. Но некоторые щемятся ославиться со своим немонотонным.
Теперь понял про монотонность. Нет, я как раз хотел бы узнать, как сделать это всё немонотонным.
Точнее монотонным)
...
Рейтинг: 0 / 0
09.12.2016, 11:36
    #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
09.12.2016, 12:22
    #39363308
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Интервальное хранение (пакуем каждодневные записи в отрезки)
DIMANNNNNПоправил.
Код: sql
1.
to_date('02.03.2016')

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


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