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

Когда "Запас накопленным итогом" становится меньше чем половина SMAX , то должна быть поставка равная
"Макс запас" - "Запас накопленным итогом" . После этого эта Поставка суммируется с "Запас накопленным итогом"

Соответственно требуется решение на PL/SQL, думаю что нужен цикл какой-нибудь или курсор, сам додуматься не могу.

Буду рад помощи.


ДатаПродажиЗапас накопленным итогомМакс запасПоставка42613101001000426432090100042674107010004270420601000427351040100042766203010004279410101000428252001000428551001000428862001000429161001000429472001000429781001000430082001000430391001000430692001000431001001000
...
Рейтинг: 0 / 0
Курсор/цикл
    #39300852
Avotge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plsql
1.
2.
3.
4.
  update ...
        set 'Запас накопленным итогом' = 'Макс запас',
              'Поставка' = 'Макс запас' - 'Запас накопленным итогом'
  where 'Запас накопленным итогом' < 'Макс запас'/2
...
Рейтинг: 0 / 0
Курсор/цикл
    #39300859
bot2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Avotge, а каким образом пересчитается запас накопленным итогом ? Таблица будет выглядеть вот так, а это неправильно:
ДатаПродажиЗапас накопленным итогомМакс запасПоставка42613101001000426432090100042674107010004270420601000427351010010060427662010010010427941010010030428252010010040428551010010010042886201001001004291610100100100429472010010010042978101001001004300820100100100430391010010010043069201001001004310010100100100


Должео быть вот так:

ДатаПродажиЗапас накопленным итогомМакс запасПоставка42613101001000426432090100042674107010004270420601000427351010010060427662090100042794107010004282520601000428551010010060428862090100042916107010004294720601000429781010010060430082090100043039107010004306920601000431001010010060
...
Рейтинг: 0 / 0
Курсор/цикл
    #39300872
Avotge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
bot2Таблица будет выглядеть вот так, а это неправильно
С чего взяли, что она будет так выглядеть, а не так которая ниже? )
Берите реальные тестовые данные (и лучше выложить их сюда, кроме самой таблицы в виде того же with-запроса) и проверяйте )
...
Рейтинг: 0 / 0
Курсор/цикл
    #39300874
Avotge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Точнее, да. Она будет выглядеть так, но по-моему представленный вами последний правильный вариант не соответствует озвученным условиям. Или я ничего не понял ).
Тестовые данные в общем нада )
...
Рейтинг: 0 / 0
Курсор/цикл
    #39300878
Avotge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Например почему для 43008 запас накопленным итого должен получиться в итоге 90?
Где это прописано в изначальной задаче и исходных данных?
Речь идет о каком-то распределении по датам, при этом в исх данных дат вообще нет.
В общем ниясна ничо )
...
Рейтинг: 0 / 0
Курсор/цикл
    #39300898
bot2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Avotge,

1) Дата не играет роли, это может быть dateid либо просто какой-либо период.

2) Условие задачи смоделировать обычную логику пополнения запасов на складе.

Запас опускается ниже определенного уровня - после этого идет пополнение до максимального запаса.


запас для даты 43008 будет 90 , потому что в предыдущий период запас был 100 и за этот период продажи были 10. 90 - 10= 90

Тестовые данные ничем не отличаются от этой таблицы , такая же таблица , только больше)

Т.е. у меня есть понимание какой ответ должен быть=)
...
Рейтинг: 0 / 0
Курсор/цикл
    #39300902
bot2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bot2, 100-10 =90 *
...
Рейтинг: 0 / 0
Курсор/цикл
    #39300912
Avotge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
bot2запас для даты 43008 будет 90, потому что в предыдущий период запас был 100 и за этот период продажи были 10. 90 - 10= 90
1. Так 43008 это дата? Не обратил внимание, решил, некий Id товара )
2. автор90 - 10= 90
Может так и бывает, но я с такими системами не работал? )))
Может 100 - 10 = 90?
3. Где в исходных данных можно понять, что в предыдущий период запас был 100? Что это за предыдущий период, учитывая, что дата пишется в виде 43008? Или имеется в виду Макс запас 100?
4. Слово продажи вообще не фигурирует в условиях задачи, зато в ходе пояснений вы активно оперируете полем продажи.

В общем надо самому четко сформулировать задачу, а там уже и сам поймешь, что и как )

bot2Тестовые данные ничем не отличаются от этой таблицы , такая же таблица , только больше)
Понятно, что не отличаются, но людям было бы легче написать запрос и проверить его.
Ближайший пример с удобными тестовыми данными, я об этом.
...
Рейтинг: 0 / 0
Курсор/цикл
    #39300917
man-from-36
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bot2
Должео быть вот так:

ДатаПродажиЗапас накопленным итогомМакс запасПоставка4306920601000

а откуда взялось 60 в запасе накопленным итогом?
...
Рейтинг: 0 / 0
Курсор/цикл
    #39300929
bishnike
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
man-from-36,

это остаток

От исходного SMAX отнимается накопительный итог по полю "продажи", как только остаток становится меньше половины, происходит его пополнение до smax колонкой "Поставка", тут надо начать заново накопительный итог по продажам и так далее.
...
Рейтинг: 0 / 0
Курсор/цикл
    #39300932
bot2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
man-from-36bot2Должео быть вот так:

ДатаПродажиЗапас накопленным итогомМакс запасПоставка4306920601000

а откуда взялось 60 в запасе накопленным итогом?

В предыдущем периоде 70 запас , а продажи 10
...
Рейтинг: 0 / 0
Курсор/цикл
    #39300949
bot2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тестовые данные



with t as
(
Select '1' as day, '10' as sales,'100' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '2' as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '3' as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '4' as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '5' as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '6' as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '7' as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '8' as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '9' as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '10' as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '11' as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '12' as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '13' as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '14' as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '15' as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '16' as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
Select '17' as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual
)

select * from t
...
Рейтинг: 0 / 0
Курсор/цикл
    #39300984
Avotge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Топатаг? )
Код: 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.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
SQL> CREATE TABLE
  2       tst AS  SELECT 42613 DAY, 10 sales, 100 stocks, 100 maxstock, 0 arrive FROM dual UNION ALL
  3             SELECT 42643, 20, 90, 100, 0 FROM dual UNION ALL
  4             SELECT 42674, 10, 70, 100, 0 FROM DUAL UNION ALL
  5             SELECT 42704, 20, 60, 100, 0 FROM DUAL UNION ALL
  6             SELECT 42735, 10, 40, 100, 0 FROM DUAL UNION ALL
  7             SELECT 42766, 20, 30, 100, 0 FROM DUAL UNION ALL
  8             SELECT 42794, 10, 10, 100, 0 FROM DUAL UNION ALL
  9             SELECT 42825, 20, 0, 100, 0 FROM DUAL UNION ALL
 10             SELECT 42855, 10, 0, 100, 0 FROM DUAL UNION ALL
 11             SELECT 42886, 20, 0, 100, 0 FROM DUAL UNION ALL
 12             SELECT 42916, 10, 0, 100, 0 FROM DUAL UNION ALL
 13             SELECT 42947, 20, 0, 100, 0 FROM DUAL UNION ALL
 14             SELECT 42978, 10, 0, 100, 0 FROM DUAL UNION ALL
 15             SELECT 43008, 20, 0, 100, 0 FROM DUAL UNION ALL
 16             SELECT 43039, 10, 0, 100, 0 FROM DUAL UNION ALL
 17             SELECT 43069, 20, 0, 100, 0 FROM DUAL UNION ALL
 18             SELECT 43100, 10, 0, 100, 0 FROM DUAL
 19  /

Table created

SQL> DECLARE
  2     v_next_stocks NUMBER;
  3  BEGIN
  4     FOR cr IN (SELECT day, LEAD(day) OVER(ORDER BY day) next_day
  5                  FROM tst
  6                 ORDER BY day)
  7     LOOP
  8        UPDATE tst
  9           SET stocks = CASE WHEN stocks < maxstock/2 THEN maxstock ELSE stocks END,
 10               arrive = CASE WHEN stocks < maxstock/2 THEN maxstock - stocks ELSE arrive END
 11         WHERE day = cr.day RETURNING stocks - sales INTO v_next_stocks;
 12  
 13        IF cr.next_day IS NOT NULL THEN
 14           UPDATE tst
 15              SET stocks = CASE WHEN v_next_stocks < maxstock/2 THEN maxstock ELSE v_next_stocks END,
 16                  arrive = CASE WHEN v_next_stocks < maxstock/2 THEN maxstock - v_next_stocks ELSE arrive END
 17            WHERE day = cr.next_day;
 18        END IF;
 19     END LOOP;
 20  END;
 21  /
 
PL/SQL procedure successfully completed

SQL> select * from tst
  2  /
 
       DAY      SALES     STOCKS   MAXSTOCK     ARRIVE
---------- ---------- ---------- ---------- ----------
     42613         10        100        100          0
     42643         20         90        100          0
     42674         10         70        100          0
     42704         20         60        100          0
     42735         10        100        100         60
     42766         20         90        100          0
     42794         10         70        100          0
     42825         20         60        100          0
     42855         10        100        100         60
     42886         20         90        100          0
     42916         10         70        100          0
     42947         20         60        100          0
     42978         10        100        100         60
     43008         20         90        100          0
     43039         10         70        100          0
     43069         20         60        100          0
     43100         10        100        100         60
 
17 rows selected

...
Рейтинг: 0 / 0
Курсор/цикл
    #39300992
arkx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
rtfm lag
...
Рейтинг: 0 / 0
Курсор/цикл
    #39301227
bishnike
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arkx,

т.е. вы знаете решение только на одном lag'е?

Всё что я смог выдавить так это рекурсивный пересчет накопительного итога,
возможно есть способ проще сделать "stop rsum", я его не нашел.

Код: 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.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
with t(dt, sales, stocks, maxstock, arrive) as (
  Select 1 as day, '10' as sales,'100' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 2 as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 3 as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 4 as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 5 as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 6 as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 7 as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 8 as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 9 as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 10 as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 11 as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 12 as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 13 as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 14 as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 15 as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 16 as day, '20' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual union
  Select 17 as day, '10' as sales,'0' as stocks, '100' as maxstock, '0' as arrive from dual 
), 
w_r (dt, sales, rsum, grp, maxstock, mgrp) as (
  select 
    dt, 
    sales,
    sum(sales)over(order by dt) as rsum,
    case when sum(sales)over(order by dt) - sales <= maxstock/2 then 1 end as grp,
    maxstock,
    1 as mgrp
  from t
  union all
  select 
    dt,
    sales,
    sum(sales)over(order by dt) as rsum,
    case when sum(sales)over(order by dt) - sales <= maxstock/2 then mgrp + 1 end as grp,
    maxstock,
    mgrp + 1 as mgrp
  from w_r
  where 1 = 1
    and grp is null and mgrp <= (select count(1) from t)
)
select 
  dt, 
  sales, 
  maxstock - rsum + sales as stocks,
  --maxstock - rsum as stocks_after,
  maxstock, 
  --rsum,
  case
    when lag(maxstock - rsum, 1, 100)over(order by dt) < maxstock/2 
      then maxstock - lag(maxstock - rsum, 1, 100)over(order by dt)
    else 0 
  end as deliv
from w_r
where 1 = 1
  and grp is not null -- отбрасываем мусор после рекурсии

...
Рейтинг: 0 / 0
Курсор/цикл
    #39301269
Avotge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Уговорили.
И без лагов/лидов и без рекурсии и с одним апдейтом в цикле вместо двух ))
Код: 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.
 CREATE TABLE
        tst AS  SELECT 42613 DAY, 10 sales, 100 stocks, 100 maxstock, 0 arrive FROM dual UNION ALL
              SELECT 42643, 20, 90, 100, 0 FROM dual UNION ALL
              SELECT 42674, 10, 70, 100, 0 FROM DUAL UNION ALL
               SELECT 42704, 20, 60, 100, 0 FROM DUAL UNION ALL
               SELECT 42735, 10, 40, 100, 0 FROM DUAL UNION ALL
               SELECT 42766, 20, 30, 100, 0 FROM DUAL UNION ALL
               SELECT 42794, 10, 10, 100, 0 FROM DUAL UNION ALL
               SELECT 42825, 20, 0, 100, 0 FROM DUAL UNION ALL
              SELECT 42855, 10, 0, 100, 0 FROM DUAL UNION ALL
              SELECT 42886, 20, 0, 100, 0 FROM DUAL UNION ALL
              SELECT 42916, 10, 0, 100, 0 FROM DUAL UNION ALL
              SELECT 42947, 20, 0, 100, 0 FROM DUAL UNION ALL
              SELECT 42978, 10, 0, 100, 0 FROM DUAL UNION ALL
              SELECT 43008, 20, 0, 100, 0 FROM DUAL UNION ALL
              SELECT 43039, 10, 0, 100, 0 FROM DUAL UNION ALL
              SELECT 43069, 20, 0, 100, 0 FROM DUAL UNION ALL
              SELECT 43100, 10, 0, 100, 0 FROM DUAL
/

DECLARE
   v_next_stocks NUMBER;
BEGIN  
   FOR cr IN (SELECT day FROM tst ORDER BY day)
   LOOP
      UPDATE tst
         SET stocks = CASE WHEN NVL(v_next_stocks, stocks) < maxstock/2 THEN maxstock ELSE NVL(v_next_stocks, stocks) END,
             arrive = CASE WHEN NVL(v_next_stocks, stocks) < maxstock/2 THEN maxstock - NVL(v_next_stocks, stocks) ELSE arrive END
       WHERE day = cr.day RETURNING stocks - sales INTO v_next_stocks;
   END LOOP;
END;


/
...
Рейтинг: 0 / 0
Курсор/цикл
    #39301468
AvotgeУговорили.
И без лагов/лидов и без рекурсии и с одним апдейтом в цикле вместо двух ))

а стоило бы, pl\sql супротив sql - слабина в прихватке
а тут можно чисто с лагом: твой первый апдейт взять и впендюрить туда лаги, потом танцевать и смеяться
я хотел написать, но у меня компьютер забрали
...
Рейтинг: 0 / 0
Курсор/цикл
    #39301676
Avotge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
танцующий джигуа стоило бы, pl\sql супротив sql - слабина в прихватке
а тут можно чисто с лагом: твой первый апдейт взять и впендюрить туда лаги, потом танцевать и смеяться
Круто, если покажешь чисто с лагом впендюренным в обычный апдейт, но сомневаюсь, что прокатит:
тут же надо еще лаг от лага брать типа рекурсии что-то )
В общем забирай комп обратно и показывай )
...
Рейтинг: 0 / 0
Курсор/цикл
    #39302317
bot2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем спасибо огромное!!!
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Курсор/цикл
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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