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

Откуда:
Сообщений: 18
Добрый вечер! Помогите, пожалуйста, решить задачку. Есть таблица Tab, в которой содержится информация о продавцах id, датах продаж и суммах продаж. Необходимо данную таблицу дополнить по каждому продавцу датами от максимально существующей до отчетной, а суммы продаж заполнить нолями.
Например, таблица Tab содержит:
Id Date Amount
222 2011-08-13 1234,43
222 2011-08-15 67,78
222 2011-08-23 67,78
333 2011-08-17 1345,00
333 2011-08-28 489,21
Отчетная дата 2011-08-31.
То есть по продавцу 222 максимальная дата продажи 2011-08-23, до отчетной еще 8 дат, которые необходимо добавить:
Id Date Amount
222 2011-08-24 0,00
222 2011-08-25 0,00
222 2011-08-26 0,00
222 2011-08-27 0,00
222 2011-08-28 0,00
222 2011-08-29 0,00
222 2011-08-30 0,00
222 2011-08-31 0,00
Аналогично по продавцу 333 – максимальная дата продажи 2011-08-28, добавляем:
Id Date Amount
333 2011-08-29 0,00
333 2011-08-30 0,00
333 2011-08-31 0,00
База очень большая, как это можно реализовать? Заранее спасибо за помощь.
19 сен 11, 23:25    [11301998]     Ответить | Цитировать Сообщить модератору
 Re: Цикл на добавление данных  [new]
qwerty112
Guest
declare @t table (Id int, Date datetime, Amount decimal(18,2))

insert into @t
select 222, '2011-08-13', 1234.43 union all
select 222, '2011-08-15', 67.78 union all
select 222, '2011-08-23', 67.78 union all
select 333, '2011-08-17', 1345.00 union all
select 333, '2011-08-28', 489.21

;with calendar as
(select cast('2011-08-01' as datetime) as dt union all select dt+1 from calendar where dt+1<='2011-08-31')

--select calendar.dt, 222 as id, isnull(Amount, 0) as Amount
--from calendar 
--left join @t t 
--  on calendar.dt=t.Date and Id=222 

--

select a.*, isnull(t1.Amount, 0) as Amount
from 
(select calendar.dt, t.id
from calendar cross join (select distinct Id from @t) t) a
left join @t t1
  on a.dt=t1.Date and a.Id=t1.Id
20 сен 11, 00:14    [11302118]     Ответить | Цитировать Сообщить модератору
 Re: Цикл на добавление данных  [new]
tel-86
Member

Откуда:
Сообщений: 18
Спасибо, qwerty112! Хотел бы уточнить: Вы указываете начальную дату 2011-08-01. Но дата может быть необязательно в 8 месяце 2011 года. Например, максимальная дата продажи n-продавца 2010-12-13, а отчетная все та же 2011-08-31. То есть мне нужно сказать, что вот по такому-то продавцу добавь даты от 2010-12-13 до 2011-08-31, суммы - ноль. Или если максимальная дата равна отчетной, то ничего не добавляй. Возможно просто в какую-то промежуточную таблицу по каждому продавцу выбрать максимальную дату продажи? А потом как ее добавить в цикл?
20 сен 11, 00:37    [11302154]     Ответить | Цитировать Сообщить модератору
 Re: Цикл на добавление данных  [new]
iljy
Member

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

заведите себе таблицу-календарь и выбирайте из нее даты нужного диапазона. Но вообще для большой базы идея странная - нафига нужно еще сильнее ее раздувать пустыми записями? Что за задачу решаете?
20 сен 11, 08:54    [11302545]     Ответить | Цитировать Сообщить модератору
 Re: Цикл на добавление данных  [new]
tel-86
Member

Откуда:
Сообщений: 18
iljy
tel-86,

заведите себе таблицу-календарь и выбирайте из нее даты нужного диапазона. Но вообще для большой базы идея странная - нафига нужно еще сильнее ее раздувать пустыми записями? Что за задачу решаете?


Мне нужно перебирать не только даты, но и продавцов. То есть первый цикл должен быть по продавцам, а второй внутренний по датам. А как это все объединить ума не приложу. Раздуваться таблица будет только во время запуска запроса, после выгрузки всех необходимых данных пустые записи удаляться. Нужно это для расчет финансовых коэффициентов.
20 сен 11, 09:49    [11302801]     Ответить | Цитировать Сообщить модератору
 Re: Цикл на добавление данных  [new]
Glory
Member

Откуда:
Сообщений: 104751
tel-86
Мне нужно перебирать не только даты, но и продавцов. То есть первый цикл должен быть по продавцам, а второй внутренний по датам. А как это все объединить ума не приложу


1. Выбрать все даты
2. Выбрать всех продовцов
3. Сделать cross join
и все это без всяких циклов
20 сен 11, 09:53    [11302828]     Ответить | Цитировать Сообщить модератору
 Re: Цикл на добавление данных  [new]
tel-86
Member

Откуда:
Сообщений: 18
Добрый день!

Написал необходимый запрос, но он не работает, так как в MS SQL нет цикла FOR, подскажите плиз, что используется в MS SQL для перебора строк? В Oracle данный скрипт отрабатывается корректно.


DECLARE
V_END_PERIOD DATE;
v NUMBER;
BEGIN

V_END_PERIOD := to_date('31.08.2011','dd.mm.yyyy');

FOR R IN (SELECT T.ID, MAX(T.ID2) MAX_DATE FROM TEST_TABLE5 T GROUP BY ID) LOOP
WHILE R.MAX_DATE < V_END_PERIOD LOOP
R.MAX_DATE := R.MAX_DATE + 1;
DBMS_OUTPUT.PUT_LINE('прод:' || R.ID || ' дата:' || R.MAX_DATE);
INSERT INTO TEST_TABLE5 VALUES (R.ID,R.MAX_DATE,0);



END LOOP;

END LOOP;

END;
20 сен 11, 14:11    [11305417]     Ответить | Цитировать Сообщить модератору
 Re: Цикл на добавление данных  [new]
tel-86
Member

Откуда:
Сообщений: 18
Glory, спасибо за идею, это как альтернативный вариант, но он к сожалению мне не совсем подходит, так как очень большая БД и выдает ошибку, что не может про join все поля.
20 сен 11, 14:15    [11305461]     Ответить | Цитировать Сообщить модератору
 Re: Цикл на добавление данных  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
tel-86
Glory, спасибо за идею, это как альтернативный вариант, но он к сожалению мне не совсем подходит, так как очень большая БД и выдает ошибку, что не может про join все поля.
Я вам советую никому не говорить, где вы живете, особенно после того, как вы уволитесь, чтобы избежать встречи с тем человеком, который будет после вас поддерживать ваши _основные_ варианты, да.
20 сен 11, 14:22    [11305542]     Ответить | Цитировать Сообщить модератору
 Re: Цикл на добавление данных  [new]
iljy
Member

Откуда:
Сообщений: 8711
Еще одно подтверждение...
20 сен 11, 14:38    [11305734]     Ответить | Цитировать Сообщить модератору
 Re: Цикл на добавление данных  [new]
Yuriy Petrov
Member

Откуда:
Сообщений: 91
tel-86
Добрый вечер! Помогите, пожалуйста, решить задачку. Есть таблица Tab, в которой содержится информация о продавцах id, датах продаж и суммах продаж. Необходимо данную таблицу дополнить по каждому продавцу датами от максимально существующей до отчетной, а суммы продаж заполнить нолями.
Например, таблица Tab содержит:
Id Date Amount
222 2011-08-13 1234,43
222 2011-08-15 67,78
222 2011-08-23 67,78
333 2011-08-17 1345,00
333 2011-08-28 489,21
Отчетная дата 2011-08-31.
То есть по продавцу 222 максимальная дата продажи 2011-08-23, до отчетной еще 8 дат, которые необходимо добавить:
Id Date Amount
222 2011-08-24 0,00
222 2011-08-25 0,00
222 2011-08-26 0,00
222 2011-08-27 0,00
222 2011-08-28 0,00
222 2011-08-29 0,00
222 2011-08-30 0,00
222 2011-08-31 0,00
Аналогично по продавцу 333 – максимальная дата продажи 2011-08-28, добавляем:
Id Date Amount
333 2011-08-29 0,00
333 2011-08-30 0,00
333 2011-08-31 0,00
База очень большая, как это можно реализовать? Заранее спасибо за помощь.


Вариант с рекурсией:
declare @t table (
	id int,
	dt datetime,
	amount money
);

declare @dt datetime = getdate ();	-- report date

insert into @t
values	(1, GETDATE() - 3, 1),
		(2, GETDATE() - 4, 2),
		(3, GETDATE() - 5, 3),
		(4, GETDATE(), 4);

with cte
as (
	select id, MAX (dt) + 1 as [dt]
	  from @t
	 group by id
	having MAX (dt) + 1 <= @dt
	
	union all
	
	select id, dt + 1
	  from cte
	 where dt + 1 <= @dt
)
select id, dt, 0.0 as [amount]
  from cte
 order by id, dt
option (maxrecursion 0);
20 сен 11, 15:05    [11306035]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить