Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите посчитать количество дней которые товар был на складе  [new]
mvg_first
Member

Откуда: Украина г. Кривой Рог
Сообщений: 112
Есть таблица "Обороты товара":
CREATE TABLE [RA219] (

[IDDOC] [char] (9) COLLATE Cyrillic_General_CI_AS NOT NULL , --Идентификатор документа

[DATE_TIME_IDDOC] [char] (23) COLLATE Cyrillic_General_CI_AS NOT NULL , -- Дата+Время+Идентификатор документа

[SP290] [char] (9) COLLATE Cyrillic_General_CI_AS NOT NULL , -- Идентификатор Контрагента

[SP291] [char] (9) COLLATE Cyrillic_General_CI_AS NOT NULL , -- Идентификатор Товара

[SP292] [numeric](18, 3) NOT NULL , -- Количество прихода товара

[SP294] [numeric](18, 3) NOT NULL , -- Количество расхода товара

) ON [PRIMARY]

Нужно получить количество дней во время которых товар находился в организации (Количество_Прихода-Количество_Расхода <> 0). Т.е. нужно подсчитать количество дней в промежутках когда товар был на складах орагнизации. и не считать те промежутки когда товара небыло.
16 май 03, 16:45    [201467]     Ответить | Цитировать Сообщить модератору
 Re: Помогите посчитать количество дней которые товар был на складе  [new]
mvg_first
Member

Откуда: Украина г. Кривой Рог
Сообщений: 112
Да, еще забыл добавить записи добавляются в эту таблицу документами (идентификаторы которых указаны в поле Iddoc). Т.е. есть некая "Приходная накладная" которая добавляет в базу строку с датой и количеством прихода, и есть некая "Расходная накладная" которая добавляет в эту таблицу строку с датой и количеством расхода.
16 май 03, 17:02    [201507]     Ответить | Цитировать Сообщить модератору
 Re: Помогите посчитать количество дней которые товар был на складе  [new]
mvg_first
Member

Откуда: Украина г. Кривой Рог
Сообщений: 112
Если нет идей - то подскажите хотя бы как получить итоги по приходу и расходу с группированные по датам но что бы дискретность даты была 1 день.

Блин - намолол чегото - но надеюсь вы понимаете что я имел ввиду.

Есть одна идея получить остатки товара на каждый день и посчитать количество строк в результате.
16 май 03, 18:09    [201596]     Ответить | Цитировать Сообщить модератору
 Re: Помогите посчитать количество дней которые товар был на складе  [new]
fte
Member

Откуда: Moscow
Сообщений: 386
А зачем у тебя
"[DATE_TIME_IDDOC] [char] (23)",
сделать два поля
[DT] [Datetime]
[IDDOC] [char]
по-моему намного правильнее! Да и запросы писать намного проще....
16 май 03, 18:37    [201618]     Ответить | Цитировать Сообщить модератору
 Re: Помогите посчитать количество дней которые товар был на складе  [new]
Luchkin Dmitry
Member

Откуда: Новосибирск -> Ангарск -> Братск -> Мск
Сообщений: 1921
sorry. после пива могу намолоть полную ахинею. но имхо эт выглядит примерно так:
CREATE TABLE [#RA219] (

[IDDOC] [char] (9) COLLATE Cyrillic_General_CI_AS NOT NULL , --Идентификатор документа

[DATE_TIME_IDDOC] [char] (23) COLLATE Cyrillic_General_CI_AS NOT NULL , -- Дата+Время+Идентификатор документа

[SP290] [char] (9) COLLATE Cyrillic_General_CI_AS NOT NULL , -- Идентификатор Контрагента

[SP291] [char] (9) COLLATE Cyrillic_General_CI_AS NOT NULL , -- Идентификатор Товара

[SP292] [numeric](18, 3) NOT NULL , -- Количество прихода товара

[SP294] [numeric](18, 3) NOT NULL , -- Количество расхода товара

) ON [PRIMARY]

declare @dDate smalldatetime
set @dDate= cast(round(cast(GetDate() as float), 0, 1) as smalldatetime)
insert #ra219 values(1, @dDate, '1', '1', 1, 0) -- Приход 1 штуки

insert #ra219 values(2, @dDate+1, '1', '1', 1, 0) -- Приход 1 штуки

insert #ra219 values(3, @dDate+3, '1', '1', 0, 1) -- Расход 1 штуки

insert #ra219 values(3, @dDate+4, '1', '1', 0, 1) -- Расход 1 штуки


declare @dMin smalldatetime, @dMax smalldatetime
select @dMin= min(date_time_iddoc), @dMax= max(date_time_iddoc) from #ra219

create table #tempDat (Data smalldatetime)
while @dMin <= @dMax begin
insert #tempDat VALUES (@dMin)
set @dMin= @dMin+1
end

select Dat.Data, sum(ra.sp292)-sum(ra.sp294) as Sal from #tempDat Dat, #ra219 ra
where ra.date_time_iddoc <= Dat.Data
group by Dat.Data

select * from #tempDat
select * from #ra219

drop table #ra219
drop table #tempDat


боюсь, что лучше сможет только SergSuper :)
16 май 03, 18:40    [201626]     Ответить | Цитировать Сообщить модератору
 Re: Помогите посчитать количество дней которые товар был на складе  [new]
mvg_first
Member

Откуда: Украина г. Кривой Рог
Сообщений: 112
fte
Вообще то эти таблицы придумывал не я. Это великие гении из 1С :) Так что структур таблиц менять не могу, придется выкручиваться тем что есть.
16 май 03, 18:43    [201636]     Ответить | Цитировать Сообщить модератору
 Re: Помогите посчитать количество дней которые товар был на складе  [new]
mvg_first
Member

Откуда: Украина г. Кривой Рог
Сообщений: 112
Luchkin Dmitry

А без цикла никак нельзя? Так что бы одним запросом получить? Дело в том что я хочу потом получившийся результат подключить как подзапрос???
16 май 03, 18:47    [201639]     Ответить | Цитировать Сообщить модератору
 Re: Помогите посчитать количество дней которые товар был на складе  [new]
Luchkin Dmitry
Member

Откуда: Новосибирск -> Ангарск -> Братск -> Мск
Сообщений: 1921
1. без цикла наверное низзя.
2. этот цикл нужно сделать заранее, дабы сформировать табличку с перечисленными датами внутри отчётного периода. Ведь вопрос "сколько дней сальдо было больше нуля" только тогда имеет смысл, когда указывается внутри какого периода считать.
Т.о. вначале вы должны запросить дату начала/конца отчёта; сформировать таблицу с датами в цикле. и уж потом тот один нужно запрос подключайте как подзапрос скока душе угодно.
16 май 03, 18:55    [201648]     Ответить | Цитировать Сообщить модератору
 Re: Помогите посчитать количество дней которые товар был на складе  [new]
mvg_first
Member

Откуда: Украина г. Кривой Рог
Сообщений: 112
Период запроса будет заваться всегда :)
Но я непонимаю зачем мне держать таблицу сформированно? если дискретизация которую я хочу получить весьма и весьма распространненное понятие. И используется во многих аналитических запросах??? Зачем мне хранить календарь в виде таблицы????

Или вот каким образом мне получить табличу содержащую общий итог по каждому товару, вложенную группировку для каждого товара по датам с дискретизацией до одного дня?

Понимаете о чем я?
16 май 03, 19:02    [201656]     Ответить | Цитировать Сообщить модератору
 Re: Помогите посчитать количество дней которые товар был на складе  [new]
Luchkin Dmitry
Member

Откуда: Новосибирск -> Ангарск -> Братск -> Мск
Сообщений: 1921
imho опять-же.
либо св результате будут только даты, когда был хотябы один приход или расход, либо нужно строить таблицу.
другхой путя мне не известно :)
16 май 03, 19:09    [201660]     Ответить | Цитировать Сообщить модератору
 Re: Помогите посчитать количество дней которые товар был на складе  [new]
mvg_first
Member

Откуда: Украина г. Кривой Рог
Сообщений: 112
Понял, буду пробовать использовать таблицы в памяти (т.к. они по объему небольшие).
Но все же вопрос остается открытым, может кто нибудь придложит еще какое-нибудь решение?
16 май 03, 19:16    [201665]     Ответить | Цитировать Сообщить модератору
 Re: Помогите посчитать количество дней которые товар был на складе  [new]
SergSuper
Member

Откуда: SPb
Сообщений: 5488
Не хотел ничего писать, но раз уж начали меня склонять...

Есть еще такой способ, без цикла:
 declare @t table(tovar varchar(20), date datetime, prihod int, racx int)


insert @t
select 'рога', '20030101',1,0
union select 'рога', '20030103',2,0
union select 'рога', '20030104',0,3
union select 'рога', '20030106',2,0
union select 'рога', '20030109',0,2
union select 'копыта', '20030104',2,0
union select 'копыта', '20030107',0,2

select tovar, sum(datediff(dd,date, '20030101')*ost)
from
(select t1.tovar, t1.date, case when sum(t2.prihod-t2.racx)>=0 then -1 else 1 end ost
from @t t1, @t t2
where t1.tovar=t2.tovar and t2.date<=t1.date
group by t1.tovar, t1.date) as xxx
group by tovar


Нужно что бы товар в конце концов заканчивался либо надо сравнивать с датой, на какое число считается (у меня '20030101').
И еще момент - если 1-го числа товар положили, а 2-го сняли - то будет считаться что товар был 1 день (т.е. 2 - 1 = 1).
Всё это можно немного подумав исправить - главное поймите принцип. Поняв может убедитесь что идея Luchkin Dmitry подойдет больше :)

И чего-то подобное я когда-то давно делал, посмотрите.
Хотя не знаю, меня то никто не учил, никто ничего не показывал (ну собственно и некому было), может быть всё-таки полезней сначала самому подумать, чем сразу у кого-то спрашивать? Когда знаешь что решать проблемму надо, а помощи ждать неоткуда - как-то оно получше думается.
16 май 03, 19:57    [201694]     Ответить | Цитировать Сообщить модератору
 Re: Помогите посчитать количество дней которые товар был на складе  [new]
mvg_first
Member

Откуда: Украина г. Кривой Рог
Сообщений: 112
Да я эту проблему уже два дня сам обдумываю :) Но со мной случилась истерика, от того что неполучается ничего (да и конец недели всетаки) вот я и решил спросить совета у общественности.
16 май 03, 20:56    [201717]     Ответить | Цитировать Сообщить модератору
 Re: Помогите посчитать количество дней которые товар был на складе  [new]
SergSuper
Member

Откуда: SPb
Сообщений: 5488
Да уж, ерунду в пятницу написал
Это называется головокружение от успехов
Вот так вроде правильно. Правда приходиться делать еще через одну таблицу, но я в этом ничего плохого не вижу.
declare @t table(tovar varchar(20), date datetime, prihod int, racx int)


insert @t
select 'рога', '20030101',1,0
union select 'рога', '20030103',2,0
union select 'рога', '20030104',0,3
union select 'рога', '20030106',2,0
union select 'рога', '20030109',0,2
union select 'копыта', '20030104',2,0
union select 'копыта', '20030107',0,2


declare @d table(tovar varchar(20), date datetime, summa int)

insert @d
select t1.tovar, t1.date, sum(t2.prihod-t2.racx) ost
from @t t1, @t t2
where t1.tovar=t2.tovar and t2.date<=t1.date
group by t1.tovar, t1.date

select * from @d d
where (summa<=0) or not exists(select * from @d d1 where d1.tovar=d.tovar and d1.date<d.date and summa>0
and not exists(select * from @d d2 where d2.tovar=d.tovar and d2.date<d.date and d2.date>d1.date and summa<=0))
order by tovar, date

select tovar, sum(datediff(dd,date, '20030101')*case when summa<=0 then -1 else 1 end)
from @d d
where (summa<=0) or not exists(select * from @d d1 where d1.tovar=d.tovar and d1.date<d.date and summa>0
and not exists(select * from @d d2 where d2.tovar=d.tovar and d2.date<d.date and d2.date>d1.date and summa<=0))
group by tovar
19 май 03, 10:24    [202323]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить