powered by simpleCommunicator - 2.0.39     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Покрытие заявок приходами по приоритетам - как обойтись без процедурной логики?
10 сообщений из 10, страница 1 из 1
Покрытие заявок приходами по приоритетам - как обойтись без процедурной логики?
    #38995553
Дано: таблица заявок:
Код: sql
1.
2.
3.
4.
5.
6.
create table dbo.Claims (
  id int not null identity primary key,
  сreated datetime not null,
  item varchar(50) not null,
  quantity float
)


и таблица приходов по этим заявкам:
Код: sql
1.
2.
3.
4.
5.
create table dbo.Incomings (
  id int not null identity primary key,
  item varchar(50) not null,
  quantity float
)


Необходимо заполнить таблицу соответствия приходов заявкам:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
create table zcx.IncomingLinks (
  id int identity not null primary key,
  claim_id int not null,
  incoming_id int not null,
  quantity float not null,
  constraint fk_claim_id foreign key (claim_id) references dbo.Claims (id),
  constraint fk_incoming_id foreign key (incoming_id) references dbo.Incomings (id)
)


Связь прихода и заявки - по полю item
Нюансы:
1. В позиции прихода может быть меньшее количество, чем в заявке - тогда вставляем именно то количество, которое в приходе; при появлении следующего прихода на тот же item добавляем новую запись - и так до тех пор, пока количество, указанное в заявке, не будет меньшим или равным суммарному количеству по приходам.
2. В приходах на отдельно взятый item количество записей может быть меньше, чем заявок на этот же item - в это случае заявки привязываются по возрастанию срока создания. Заявки, на которые не хватило прихода, оставляем в ожидании следующих приходов.
3. Если в приходе количество больше, чем в отдельно взятой заявке, то на заявку распределяем столько, сколько указано в заявке, остаток распределяем на следующую заявку в соответствии с приоритетом (сроком) заявки, остаток, ели он еще есть - на следующую, итд, пока не выберем всё количество по приходу.
4. Если по приходу всё имеющееся количество распределено по заявкам, то такие приходы для связывания больше не рассматриваются.
Пример:
Заявки:
idcreateditemquantity101.01.2015Петрушка1202.01.2015Укроп2303.01.2015Петрушка50404.01.2015Укроп50505.01.2015Килька50
Приходы:
iditemquantity1Петрушка402Укроп403Килька40
Распределение:
idclaim_idincoming_idquantity11112313932224423855340
(и при наличии следующих приходов на заявку 3 надо будет дораспределить 11б на заявку 4 - 12, на заявку 5 - 10).
Пока удалось родить только простыню мрачных процедурных конструкций с курсорами и if'ами. Вопрос: можно ли вышеописанное сделать запросом?
Делается для 2005-го сервера.
...
Рейтинг: 0 / 0
Покрытие заявок приходами по приоритетам - как обойтись без процедурной логики?
    #38995577
Фотография Maxx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Заявки-приходыВопрос: можно ли вышеописанное сделать запросом?

а кто вызывать запрос то будет ?
...
Рейтинг: 0 / 0
Покрытие заявок приходами по приоритетам - как обойтись без процедурной логики?
    #38995585
Maxxа кто вызывать запрос то будет ?
Клиентское приложение (задание по расписанию в windows scheduler'е).
...
Рейтинг: 0 / 0
Покрытие заявок приходами по приоритетам - как обойтись без процедурной логики?
    #38995589
Фотография Maxx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Заявки-приходыMaxxа кто вызывать запрос то будет ?
Клиентское приложение (задание по расписанию в windows scheduler'е).
и вы каждый раз будете ве пересчитывать ?
Просто любопытно ..а так ,то путь решения есть в ФАКЕ по форуму.
...
Рейтинг: 0 / 0
Покрытие заявок приходами по приоритетам - как обойтись без процедурной логики?
    #38995601
Maxxи вы каждый раз будете ве пересчитывать ?
Нет, не всё - только по приходам и заявкам, не поставленным в соответствие, и по которым не покрыто всё количество. От периодичности пересчета тут в любом случае не уйти, т.к. будут появляться новые заявки/приходы, которые нужно связывать. При определенном периоде пересчета (думаю, 1 раз в час) объем пересчитываемых данных будет не такой уж и большой.
MaxxПросто любопытно ..а так ,то путь решения есть в ФАКЕ по форуму.
подразумевается статья про нарастающий итог?
...
Рейтинг: 0 / 0
Покрытие заявок приходами по приоритетам - как обойтись без процедурной логики?
    #38995625
Фотография Maxx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Заявки-приходыПри определенном периоде пересчета (думаю, 1 раз в час) объем пересчитываемых данных будет не такой уж и большой.

я , конечно,не на что не намекаю...но у вас нет не одного поля в таблицах которое рассказало что считать не надо

Заявки-приходыподразумевается статья про нарастающий итог?
И она тоже,а так списание методом FIFO
...
Рейтинг: 0 / 0
Покрытие заявок приходами по приоритетам - как обойтись без процедурной логики?
    #38995801
В приниципе, все вполне работает вот так:
Код: 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.
45.
46.
47.
48.
49.
50.
51.
declare
  cr cursor local for
    with cte as (
      select
        l.id, l.item, l.created, l.quantity,
        l.quantity-isnull(f.purchased, 0) rest,
        row_number() over(partition by l.item order by l.created) priority
      from dbo.claims l
      outer apply (
        select sum(i.quantity)
        from dbo.IncomingLinks i
        where i.claim_id=l.id
      )f(purchased)
    )
    select id, item, rest from cte
    where rest>0
    order by item desc, priority
declare
  @id int,
  @incoming_id int,
  @item varchar(50),
  @rest float,
  @purchased float;
open cr;
while 1=1
begin
  fetch next from cr into @id, @item, @rest;
  if @@fetch_status<>0 break;
  while 1=1
  begin
    set @purchased=null;
    select top 1
      @incoming_id=id,
      @purchased=case when i.quantity - isnull(f.purchased, 0)>@rest then @rest else i.quantity - isnull(f.purchased, 0) end
    from dbo.Incomings i
    outer apply (
      select sum(l.quantity)
      from dbo.IncomingLinks l
      where l.incoming_id=i.id
    )f(purchased)
    where i.item=@item and i.quantity>isnull(f.purchased, 0)
    order by i.id
    if @purchased is null break;
    insert into dbo.IncomingLinks(claim_id, incoming_id, quantity)
      values(@id, @incoming_id, @purchased);
    if @purchased=@rest break;
    set @rest=@rest-@purchased;
  end;
end;
close cr;
deallocate cr;


- но вот эта процедурная простыня мне не нравится. Попробовал запрос внутри курсорного цикла переделать в рекурсивное cte - не выходит, в них нельзя использовать top и агрегаты. А что еще тут можно сделать, как-то не соображу.
...
Рейтинг: 0 / 0
Покрытие заявок приходами по приоритетам - как обойтись без процедурной логики?
    #38995815
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Заявки-приходы, Вам шашечки или ехать?
...
Рейтинг: 0 / 0
Покрытие заявок приходами по приоритетам - как обойтись без процедурной логики?
    #38995834
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Покрытие заявок приходами по приоритетам - как обойтись без процедурной логики?
    #38996065
Владислав КолосовЗаявки-приходы, Вам шашечки или ехать?
Мне ехать, но побыстрее - не раз сталкивался с ситуацией, когда в MSSQL процедурная логика ощутимо медленне запросной.
invm http://www.sql.ru/forum/1018035/zadachka-pro-yabloki-ili-sliyanie-2h-tablic
Ага, спасибо, именно то, что нужно. Получилось так:
Код: 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.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
;with cte as (
  select
    l.id, l.item, l.created, l.quantity,
    l.quantity-isnull(f.purchased, 0) rest,
    row_number() over(partition by l.item order by l.created) priority
  from dbo.claims l
  outer apply (
    select sum(i.quantity)
    from dbo.IncomingLinks i
    where i.claim_id=l.id
  )f(purchased)
  where l.quantity-isnull(f.purchased, 0)>0
), Claims as (
  select
    t1.id, t1.item, t1.rest,
    isnull(sum(t2.rest), 0) + 1 as p_QuantityStart, isnull(sum(t2.rest), 0) + t1.rest as p_QuantityEnd
  from cte t1
  left join cte t2 on t2.item=t1.item and t2.priority<t1.priority
  group by t1.id, t1.item, t1.rest
), cte2 as (
  select
    i.id, i.item, i.quantity-isnull(f.[distributed], 0) rest,
    row_number() over(partition by i.item order by i.id) priority
  from dbo.Incomings i
  outer apply (
    select
      sum(l.quantity)
    from dbo.IncomingLinks l
    where l.incoming_id=i.id
  )f([distributed])
  where i.quantity-isnull(f.[distributed], 0)>0
), Incomings as (
  select
    t1.id, t1.item, t1.rest,
    isnull(sum(t2.rest), 0) + 1 as g_QuantityStart, isnull(sum(t2.rest), 0) + t1.rest as g_QuantityEnd
  from cte2 t1
  left join cte2 t2 on t2.item=t1.item and t2.priority<t1.priority
  group by t1.id, t1.item, t1.rest
)
insert into dbo.IncomingLinks(claim_id, incoming_id, quantity)
select
  p.id, g.id,
 case
  when p.p_QuantityStart >= g.g_QuantityStart and p.p_QuantityEnd <= g.g_QuantityEnd then p.rest
  when g.g_QuantityStart >= p.p_QuantityStart and g.g_QuantityEnd <= p.p_QuantityEnd then g.rest
  when g.g_QuantityStart between p.p_QuantityStart and p.p_QuantityEnd then p.p_QuantityEnd - g.g_QuantityStart + 1
  when g.g_QuantityEnd between p.p_QuantityStart and p.p_QuantityEnd then g.g_QuantityEnd - p.p_QuantityStart + 1
 end
from Claims p
join Incomings g on
  g.item=p.item and
  p.p_QuantityStart <= g.g_QuantityEnd and
  p.p_QuantityEnd >= g.g_QuantityStart
order by 1,2
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Покрытие заявок приходами по приоритетам - как обойтись без процедурной логики?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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