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

Откуда:
Сообщений: 21
Есть таблица table1 (Code varchar,jr_date datetime,dvij numeric),где code - код товара, jr_date - дата, dvij - количество перемещений и таблица table2 (Code varchar,rest numeric,day datetime),где code-код товара, rest - остаток товара на момент времени day. Небходимо подсчитать количество дней,когда товар присутствовал на складе,за какой-то период (к примеру год). Я организовал подсчет путем перебора каждого товара и движений по нему
 set @i=1
while @i<=@count
begin
    select @code=code,@jr_date=jr_date,@dvij=dvijenie from #temptable where rowid=@i 
    ......
    if (@fcode=@code)
        begin
            if (@ost+@dvij)>0 and @k=1
                begin
                    set @ost=@ost+@dvij
                end
            else if (@ost+@dvij)>0 and (@k=0)
     ......(остальные условия и проверки и конечное определение дней присутствия товара)....
    set @i=@i+1
end
Так вот вопрос,можно ли сделать это без цикла для каждого товара,а как-нибудь хитрым запросом или другими обходными методами?
7 окт 09, 14:02    [7753484]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
aleks2
Guest
Что-то сложными путями ходите. Приведите определения таблиц и укажите признак отсутствия товара на складе.
7 окт 09, 14:08    [7753539]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
CMeP4
Member

Откуда:
Сообщений: 21
Изменить структуру базы нельзя,значит и добавить признак отсутствия я не могу. Все движения и остатки выдираю из 6 таблиц и загоняю во временные
7 окт 09, 14:34    [7753703]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
iljy
Member

Откуда:
Сообщений: 8711
CMeP4,

Все вышесказанное не повод использовать курсор. Приведите скрипты таблиц, связи и тестовые данные
7 окт 09, 14:38    [7753732]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
CMeP4
Member

Откуда:
Сообщений: 21
Может перефразируем вопрос - как получить признак отсутсвия товаров используя только данные таблицы одним select - ом?
7 окт 09, 14:40    [7753747]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
iljy
Member

Откуда:
Сообщений: 8711
CMeP4,

может вы не сами себе вопросы будете задавать, а на наши отвечать? Что для вас является признаком присутствия товара на складе? Какие данные в таблицах? Что нужно из них получить?
7 окт 09, 14:45    [7753786]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
vino
Member

Откуда:
Сообщений: 1191
CMeP4
Изменить структуру базы нельзя,значит и добавить признак отсутствия я не могу. Все движения и остатки выдираю из 6 таблиц и загоняю во временные
вас просили описать словами - как определить отсутствие товара на складе?
Разве не достаточно только в таблице table2(Code varchar,rest numeric,day datetime) данных, о чем и заметил aleks2?
но скорее всего вы не объяснили модель ведения учета, поэтому и не понятно, зачем вам движения, если остаток на каждый день уже известен.
Поэтому лучше приведите тестовый набор
7 окт 09, 14:46    [7753788]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
Glory
Member

Откуда:
Сообщений: 104760
CMeP4
Может перефразируем вопрос - как получить признак отсутсвия товаров используя только данные таблицы одним select - ом?

https://www.sql.ru/forum/actualthread.aspx?tid=127456 п.4 и п.6
7 окт 09, 14:58    [7753882]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
CMeP4
Member

Откуда:
Сообщений: 21
Действительно,плохо все объяснил. Остаток товара имеется только на 1-ое число месяца и хранится в таблице table2,а в table1 выбираем движение с 1-ого числа (текущий дени - 365) по текущий день .

#table1
Codejr_datedvijenie
0001T 2008-10-02 00:00:005
0001T 2008-10-03 00:00:00-1
0001T 2008-10-06 00:00:00-1
0001T 2008-10-10 00:00:00-1
0001T 2008-10-11 00:00:00-2
0001T 2008-10-20 00:00:005
0001T 2008-10-21 00:00:00-1
0001T 2008-10-23 00:00:00-1
0001T 2008-10-29 00:00:00-1
0001T 2008-10-30 00:00:003
0001T 2008-11-03 00:00:00-1
0001T 2008-11-05 00:00:00-1
0001T 2008-11-07 00:00:00-1
0001T 2008-11-10 00:00:00-1
0001T 2008-11-12 00:00:00-1
0001T 2008-11-19 00:00:005
0001T 2008-11-26 00:00:00-1
0001T 2008-11-27 00:00:00-1
.... ..........

#table2
Code OstatkiProdaj
0001C 00
0001H 00
0001T 058
0001T.OS 00
0001T.VZ 00
0002C 00
0002H 00
0002T 01
0002T.OS 00
0003H 00
0003T 06
..... .........
7 окт 09, 15:12    [7753974]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
aleks2
Guest
select OKM.Code, OKM.[ДатаКонцаМесяца], DT.[ДатаДвижения]
, OKM.[Остаток]+SUM(DT.[Движение]) [КоличествоТовараНаДеньДвижения]
, case WHEN OKM.[Остаток]+SUM(DT.[Движение])>0 THEN 1 ELSE 0 END [НаличиеТовараНаСкладе]
from 
[ОстаткиНаКонецМесяца] OKM
INNER JOIN
[ДвижениеТоваров] DT
ON 
OKM.Code=DT.Code 
AND OKM.[ДатаКонцаМесяца]<DT.[ДатаДвижения] 
AND DT.[ДатаДвижения]<=DATEADD(month, 1, OKM.[ДатаКонцаМесяца])
LEFT OUTER JOIN
[ДвижениеТоваров] DT1
ON 
OKM.Code=DT.Code 
AND OKM.[ДатаКонцаМесяца]<DT1.[ДатаДвижения] 
AND DT1.[ДатаДвижения]<=DT.[ДатаДвижения]
GROUP BY 
OKM.Code, OKM.[Остаток], OKM.[ДатаКонцаМесяца], DT.[ДатаДвижения]
Ну, а дальше всего то делов - найти интервалы непрерывности для [НаличиеТовараНаСкладе]=0...
Это мне уже лень.
7 окт 09, 18:00    [7755077]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
aleks2
Guest
Пардон... в суммах следует читать так
, OKM.[Остаток]+SUM(DT1.[Движение]) [КоличествоТовараНаДеньДвижения]
, case WHEN OKM.[Остаток]+SUM(DT1.[Движение])>0 THEN 1 ELSE 0 END [НаличиеТовараНаСкладе]
7 окт 09, 18:02    [7755091]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
CMeP4
Member

Откуда:
Сообщений: 21
Моей двухнедельной практики не хватает,что бы полностью понять ваш запрос . Но он работает. Также, я все еще не могу понять, как подсчитать интервалы непрерывности из полученной таблицы одним запросом.
8 окт 09, 12:07    [7757806]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
vino
Member

Откуда:
Сообщений: 1191
CMeP4, тогда стоит почитать здесь
8 окт 09, 13:06    [7758250]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
aleks2
Guest
CMeP4
Но он работает.

Я тоже в изумлении... видимо с годами оно приходит...

CMeP4
Также, я все еще не могу понять, как подсчитать интервалы непрерывности из полученной таблицы одним запросом.

Не надо одним. Не существует для T-SQL алгоритма быстрого определения интервалов непрерывности одним запросом.
8 окт 09, 13:14    [7758323]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
Slider_spb
Member

Откуда:
Сообщений: 800
Почитайте статью Работа с множествами в Transact-SQL может поможет...
8 окт 09, 14:13    [7758778]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
CMeP4
Member

Откуда:
Сообщений: 21
Посидел,почитал все то,что вы предложили,но,к сожалению,пока знаний недостаточно. Поэтому реализовал дальнейший подсчет дней присутствия через цикл. Спасибо всем за помощь,есть чему учиться и к чему стремиться
8 окт 09, 18:36    [7760994]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
vino
Member

Откуда:
Сообщений: 1191
CMeP4, и все-таки, какие сложности? был ли смысл переделывать в запрос только часть, может, надо выложить промежуточный результат и еще подумать?
8 окт 09, 19:06    [7761077]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
CMeP4
Member

Откуда:
Сообщений: 21
Начало периода хранится в переменной,конец периода - текущий день. Остаток на начало периода храниться в таблице table2. Вот промежутачная таблица table1,из которой надо посчитать дни присутствия товара.
Код ДатаДвиженияТовараКоличествоТовараПослеДвиженияПрисутствиеНаСкладе
0002T 2009-07-01 00:00:00.0001.000001
0002T 2009-07-01 00:00:00.0001.000001
0002T 2009-07-03 00:00:00.0000.000000
0003T 2008-10-29 00:00:00.0001.000001
0003T 2008-10-30 00:00:00.0000.000000
0003T 2009-02-23 00:00:00.0001.000001
0003T 2009-02-25 00:00:00.0000.000000
0003T 2009-05-27 00:00:00.0001.000001
0003T 2009-05-28 00:00:00.0000.000000
0003T 2009-07-16 00:00:00.0001.000001
0003T 2009-07-18 00:00:00.0000.000000
0003T 2009-09-11 00:00:00.0002.000001
0003T 2009-09-12 00:00:00.0000.000000
0006T 2008-11-18 00:00:00.0001.000001
0006T 2008-11-19 00:00:00.0000.000000
0007T 2009-04-07 00:00:00.0001.000001
0007T 2009-04-08 00:00:00.0000.000000
0007T 2009-07-01 00:00:00.0001.000001
0007T 2009-07-03 00:00:00.0000.000000
9 окт 09, 11:04    [7762988]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
aleks2
Guest
Так, бедолага, ты НИЧЕМУ не научишься. Извилинами то надо шевелить...
declare @t(id int identity primary key clustered, [Код] ?, [Date] datetime, Present bit)

insert @t([Код], [Date], Present)
select [Код], [ДатаДвиженияТовара],[ПрисутствиеНаСкладе]
from 
[Вот промежутачная таблица table1]
ORDER BY 
[Код], [ДатаДвиженияТовара] ASC


select T.[Код], SUM(DATEDIFF(day,T.[Date], T1.[Date])) ВсегоОтсутствовалДней
FROM 
@t T
INNER JOIN
@t T1
ON 
T.[Код]=T1.[Код]
AND
T.[id]+1=T1.[id]
WHERE 
T.Present=cast(0 as bit)
GROUP BY T.[Код]
9 окт 09, 12:05    [7763550]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
aleks2
Guest
declare @t table(id 
9 окт 09, 12:08    [7763581]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
CMeP4
Member

Откуда:
Сообщений: 21
До смещения таблици на 1 я вчера додумался,но это все-равно не работает,т.к. таблица может иметь вид
Код ДатаДвиженияТовараКоличествоТовараПослеДвиженияПрисутствиеНаСкладе
0001T 2008-10-02 00:00:00.0005.000001
0001T 2008-10-03 00:00:00.0004.000001
0001T 2008-10-06 00:00:00.0003.000001
0001T 2008-10-10 00:00:00.0002.000001
0001T 2008-10-11 00:00:00.0000.000000
0001T 2008-10-20 00:00:00.0005.000001
0001T 2008-10-21 00:00:00.0004.000001
0001T 2008-10-23 00:00:00.0003.000001
0001T 2008-10-29 00:00:00.0002.000001
0001T 2008-10-30 00:00:00.0005.000001
0001T 2008-11-03 00:00:00.0004.000001
0001T 2008-11-05 00:00:00.0003.000001
0001T 2008-11-07 00:00:00.0002.000001
0001T 2008-11-10 00:00:00.0001.000001
0001T 2008-11-12 00:00:00.0000.000000
0001T 2008-11-19 00:00:00.0005.000001
0001T 2008-11-26 00:00:00.0004.000001
0001T 2008-11-27 00:00:00.0003.000001
0001T 2008-11-29 00:00:00.0002.000001
0001T 2008-12-08 00:00:00.0000.000000


Значит надо правильно отфильтровать исходную таблицу,отфильтровав ненужное присутствие
9 окт 09, 13:27    [7764471]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
aleks2
Guest
CMeP4
До смещения таблици на 1 я вчера додумался,но это все-равно не работает,т.к. таблица может иметь вид


Ты, блин, не вещай "все-равно не работает", ты пальцем покажи: что не работает, т.е. запрос и результат.
10 окт 09, 13:07    [7768737]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
CMeP4
Member

Откуда:
Сообщений: 21
Всем спасибо за помощь,особенно alex2. Все-таки решил задачу

select code,sum(dayson) from
(
select res.code as code,min(res1.jr_date)as date1,(res.jr_date) as date2,(datediff(day,min(res1.jr_date),(res.jr_date))+1) as dayson
from #res as res with (nolock)
inner join #res as res1 with (nolock)
on res1.code=res.code and res1.ntovar=cast(1 as bit) and res1.jr_date<res.jr_date and res1.jr_date >= isnull(( select max(res2.jr_Date) from #res as res2 where res2.ntovar=cast(0 as bit) and res2.code=res.code and res2.jr_date<res.jr_date group by res2.code),@firsttime)
where res.ntovar=cast(0 as bit)
group by res.code,res.jr_date
--order by code,date2
)as tab
group by code
order by code

Только в таблицу #res предварительно пришлось записывать движение товара,если отстаток на начало прериода не был равен 0, и последний день периода усанавливать в ноль,если товар присутствовал
10 окт 09, 20:29    [7769306]     Ответить | Цитировать Сообщить модератору
 Re: Как обойтись без перебора  [new]
aleks2
Guest
CMeP4,

Ето годится на 100-10000 записей, но при больших объемах - тормоза будут охеренные.

Только две группировки, где одной то много, - чего стоят...
11 окт 09, 12:23    [7770122]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить