powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Переписать запрос
12 сообщений из 12, страница 1 из 1
Переписать запрос
    #39257391
Туплю
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
-- тестовые данные
create table tab
as
select sysdate - round(round(dbms_random.value(1, 1000))) dts, 
       cast(null as date) dtf,
       round(dbms_random.value(1, 10000)) sm from dual connect by level < 2000;

update tab
   set dtf = dts + round(dbms_random.value(1, 365));
   
-- сейчас такой запрос
select d.mon,
       count(*) cnt,
       sum(sm) sm
  from tab,
     (select add_months(trunc(min_dts, 'mm'), level-1) mon
        from (select min(dts) min_dts, max(dtf) max_dts from tab) s
      connect by level <= months_between(max_dts, min_dts) + 1) d
  where d.mon between tab.dts and tab.dtf
  group by d.mon;



То есть таблица: Дата С, Дата По, Сумма.
Нужно сгруппировать помесячно:
вывести кол-во записей и сумму на первое число каждого месяца.
Делаю в духе проктологии по-моему, в голове крутится, что должна быть какая-то простая группировка без формирования набора месяцев, без sog, но как не соображу.
...
Рейтинг: 0 / 0
Переписать запрос
    #39257422
Несплю
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Туплю,

А что смущает? Без набора месяцев не обойтись.
И, соответственно, самое простое с набором месяцев это перемножить его на tab. Что и сделано.
Если по производительности будет плохо, то оптимизировать можно через преобразование остатков в обороты.
Но это уже другая история. Работать, вероятно, будет быстрее, но запрос получится сложнее.

PS что такое sog?
...
Рейтинг: 0 / 0
Переписать запрос
    #39257438
в поиск...
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Смысл задачи умножать суммы на количество месяцев в периоде?
Лучше бы ты привел эталонные данные и результат.
...
Рейтинг: 0 / 0
Переписать запрос
    #39257440
Туплю
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
в поиск...Смысл задачи умножать суммы на количество месяцев в периоде?
Лучше бы ты привел эталонные данные и результат.
Нет. Задача ровно такая, как сформулирована. Тестовые данные и текущий результат тоже приведен.
НесплюА что смущает? Без набора месяцев не обойтись.
И, соответственно, самое простое с набором месяцев это перемножить его на tab. Что и сделано.
Если по производительности будет плохо, то оптимизировать можно через преобразование остатков в обороты.
Но это уже другая история. Работать, вероятно, будет быстрее, но запрос получится сложнее.
PS что такое sog?
Ок. Значит пусть так. sog - т.н. запрос со start of group обычно используемый для схлопывания диапазонов дат, но здесь он вообще не нужен конечно.
...
Рейтинг: 0 / 0
Переписать запрос
    #39257466
Туплю,

можно попробовать так:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
select -- Выбираем состояния на последний день периода:
       dt x_dt
     , max(cnt) keep(dense_rank last order by dto, lv) as x_cnt
     , max(sum_sm) keep(dense_rank last order by dto, lv) as x_sm
  from ( -- По сути, делаем расчет "эрланга":
         select dt, dto, lv
              , sum(cnt) over(order by dto,lv) as cnt
              , sum(sm) over(order by dto,lv) as sum_sm
           from (-- Разворачиваем диапазоны в точки смены состояний:
                  select decode(v.lv,1,dts,dtf) dto
                        , decode(v.lv,1,decode(dts,trunc(dts,'mm'),dts,last_day(trunc(dts,'mm') )+1)
                                       ,decode(dtf,trunc(dtf,'mm'),dtf,last_day(trunc(dtf,'mm') )+1)
                                ) as dt
                        , decode(v.lv,1,sm,-sm) sm
                        , decode(v.lv,1,1,-1) cnt, v.lv
                   from tab 
                   -- "Опорная" табличка на две строки, для разворота TAB
                  cross join (select level as lv from dual connect by level <= 2) v
                )
       )
 group by dt
 order by dt;

В этом случае отсутствует генерация полного набора дат по записанным в таблице периодам. Но присутствуют повышенные вложенность запроса и количество аналитических и агрегатных функций...
...
Рейтинг: 0 / 0
Переписать запрос
    #39257474
Проснулся
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Несплю,

А вот и неплохой пример преобразования остатков в обороты, который продемонстрировал нам Добрый Э - Эх.
Правда обороты у него называются "смена состояния".
Теперь осталось умножить его результат на набор месяцев и получим искомое решение :))
...
Рейтинг: 0 / 0
Переписать запрос
    #39257477
Проснулся,

сдается мне, спишь ты еще. Мой запрос возвращает ровно тот же результат, что и "проктологический" вариант ТС. А ТС, вроде как, утверждал, что результат запроса его устраивает, а не устраивает способ получения этого результата. Я показал немного другой способ. Но результат он дает такой же (ну там за небольшим исключением, которое нужно устранить при помощи HAVING)
...
Рейтинг: 0 / 0
Переписать запрос
    #39257481
Добрый Э - Эх,

Сам догадаешься, зачем нужен набор месяцев, или сразу объяснить?
...
Рейтинг: 0 / 0
Переписать запрос
    #39257566
Уже позавтракал,

где ты увидел у автора набор месяцев? у него всё благополучно урезается условием d.mon between tab.dts and tab.dtf, которое успешно вырежет все впустую сгенерированные данные. и если между мин(dts) и макс(dtf) будут "дырки" в данных, то и на выходе ровно такое же рваное покрывало автор и получит.
...
Рейтинг: 0 / 0
Переписать запрос
    #39257583
Пью кофе
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый Э - Эх,

Как думаешь в чем будет разница между его и твоим запросом, если в качестве tab использовать
Код: plsql
1.
tab as (select sysdate as dts, sysdate + 300 as dtf, 1000 as sm from dual)
...
Рейтинг: 0 / 0
Переписать запрос
    #39257597
Кофепью
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Туплю,

Кстати, в наборе месяцев нужно поставить +2 вместо +1
Код: plaintext
level <= months_between(max_dts, min_dts) + 2
...
Рейтинг: 0 / 0
Переписать запрос
    #39257717
Туплю
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Мир, дружба, жвачка )
За дырки спасибо, Добрый Э - Эх, хорошее уточнение, они-то мне пригодятся, поэтому набор дат все-таки нужен походу.
Насчет + 2 вполне возможно. Проверю, спасибо. Остановлюсь на изначальном варианте пока.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Переписать запрос
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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