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

Откуда:
Сообщений: 31
Добрый вечер!

Есть такая таблица:
create table #table
(Consultant int,
Subsidiary int,
MDate int,
CareerLevel int,
NumberOfTimesAchieved int
)

insert into #table
select 111,5,201008,220,2
union all
select 111,5,201009,230,13
union all
select 111,5,201012,240,26
union all
select 111,5,201105,250,24
union all
select 111,5,201110,260,10

select * from #table

Мне нужно сгенерировать такое число insert которое равняется NumberOfTimesAchieved для каждого отдельного CareerLevel, при том что MDate нужно увеличивать на 1
например для CareerLevel=220
должно быть так:
insert into #table2
values(111,5,201008,220),
(111,5,201009,220)
для CareerLevel = 230 должно быть 13 строк для insert
Подскажите как можно это сделать?

Заранее благодарю за ответ.
19 янв 17, 18:18    [20124164]     Ответить | Цитировать Сообщить модератору
 Re: задачка на рекурсию  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6794
nat_09,

соединяете с таблицей чисел и генерируете динамический запрос, ну или курсор если динамику не хотите
19 янв 17, 18:21    [20124183]     Ответить | Цитировать Сообщить модератору
 Re: задачка на рекурсию  [new]
лолл
Member

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

CTE
20 янв 17, 10:00    [20125756]     Ответить | Цитировать Сообщить модератору
 Re: задачка на рекурсию  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6794
лолл
nat_09,

CTE
это вы при слове рекурсия сразу забрало падает с надписью CTE ?
20 янв 17, 10:56    [20126017]     Ответить | Цитировать Сообщить модератору
 Re: задачка на рекурсию  [new]
лолл
Member

Откуда:
Сообщений: 450
TaPaK,
ваше забрало падает на крусоры?
20 янв 17, 11:21    [20126190]     Ответить | Цитировать Сообщить модератору
 Re: задачка на рекурсию  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6794
лолл,

ну если вы не всё читаете, то ладно. давайте пример на cte для

select 111,5,201008,220,22222
20 янв 17, 11:33    [20126274]     Ответить | Цитировать Сообщить модератору
 Re: задачка на рекурсию  [new]
invm
Member

Откуда: Москва
Сообщений: 9122
nat_09
Мне нужно сгенерировать такое число insert которое равняется NumberOfTimesAchieved для каждого отдельного CareerLevel, при том что MDate нужно увеличивать на 1
Для этой задачи рекурсия не нужна. Курсор и динамический SQL тоже не нужны.
Как сделать вам уже написали:
TaPaK
соединяете с таблицей чисел
Если не хотите держать постоянную таблицу чисел, можно генерировать последовательность чисел "на лету":
create function dbo.fnGenerateNumbers
(
 @Amount int
)
returns table
as
return (
 with
  a(v) as (select 0 from (values (0), (0)) t(v)),
  b(v) as (select 0 from a t1 cross join a t2),
  c(v) as (select 0 from b t1 cross join b t2),
  d(v) as (select 0 from c t1 cross join c t2),
  e(v) as (select 0 from d t1 cross join d t2),
  f(v) as (select 0 from e t1 cross join e t2)
  select top (@Amount) row_number() over (order by (select 0)) as n from f
);
20 янв 17, 11:39    [20126333]     Ответить | Цитировать Сообщить модератору
 Re: задачка на рекурсию  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6794
invm,
автор
Курсор и динамический SQL тоже не нужны.

моя понимать как просят

автор
Мне нужно сгенерировать такое число insert которое равняется

сказали генерировать insert моя генерировать, скажут вставить, моя вставит :)
20 янв 17, 11:43    [20126356]     Ответить | Цитировать Сообщить модератору
 Re: задачка на рекурсию  [new]
iap
Member

Откуда: Москва
Сообщений: 46953
WITH Data AS
(
 SELECT N=1,Consultant,Subsidiary,MDate,CareerLevel,NumberOfTimesAchieved FROM #table
 UNION ALL
 SELECT N+1,Consultant,Subsidiary,MDate+1,CareerLevel,NumberOfTimesAchieved FROM Data WHERE N<NumberOfTimesAchieved
)
INSERT #table2(Consultant,Subsidiary,MDate,CareerLevel,NumberOfTimesAchieved)
SELECT Consultant,Subsidiary,MDate,CareerLevel,NumberOfTimesAchieved
FROM Data
OPTION(MAXRECURSION 0;
20 янв 17, 12:00    [20126462]     Ответить | Цитировать Сообщить модератору
 Re: задачка на рекурсию  [new]
iap
Member

Откуда: Москва
Сообщений: 46953
C таблицей чисел [V] от 0 до ...

INSERT #table2(Consultant,Subsidiary,MDate,CareerLevel,NumberOfTimesAchieved)
SELECT T.Consultant,T.Subsidiary,T.MDate+V.number,T.CareerLevel,T.NumberOfTimesAchieved
FROM #table T
JOIN master.dbo.spt_values V ON V.type='P' AND V.number<T.NumberOfTimesAchieved;
20 янв 17, 12:06    [20126498]     Ответить | Цитировать Сообщить модератору
 Re: задачка на рекурсию  [new]
nat_09
Member

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

то, что нужно! спасибо!
20 янв 17, 14:01    [20127082]     Ответить | Цитировать Сообщить модератору
 Re: задачка на рекурсию  [new]
f50
Member

Откуда: Россия
Сообщений: 453
Коллеги, помогите тоже, голова кипит, не так часто делаю рекурсию. Вернее, делаю рекурсию по возврату строки, например для получения полного пути к ветви, а тут совсем другое... Если работать с функциями, то надо таблицу возвращать... Можно через cte, но тут в обратную сторону "раскручивается" или сам не дойду как (((

Исходные данные:
DROP TABLE t1
GO
CREATE TABLE t1 (id int, pid int, n nvarchar(15))
GO
INSERT INTO t1 (id, pid, n) VALUES (1,0,'Главный узел'), (2,1,'Узел 1'), (3,1,'Узел 2'), (4,1,'Узел 3'), (5,1,'Узел 4'), (6,1,'Узел 5'), (7,2,'Модуль 1.1'), (8,2,'Модуль 1.2'), (9,2,'Модуль 1.3'), (10,2,'Модуль 1.4'), (11,2,'Модуль 1.5'), 
(12,3,'Модуль 2.1'), (13,3,'Модуль 2.2'), (14,3,'Модуль 2.3'), (15,3,'Модуль 2.4'), (16,3,'Модуль 2.5'),
(17,7,'Деталь 1.1.1'), (18,7,'Деталь 1.1.2'), (19,7,'Деталь 1.1.3'), (20,7,'Деталь 1.1.4'), (21,7,'Деталь 1.1.5'),
(22,21,'Деталь 1.1.5.1'), (23,21,'Деталь 1.1.5.2'), (24,21,'Деталь 1.1.5.3'), (25,21,'Деталь 1.1.5.4'), (26,21,'Деталь 1.1.5.5')
GO


Надо выбрать все ID ветвей входящие например в ID=7.
SELECT * FROM t1 WHERE pid=7
2 июн 17, 14:27    [20534941]     Ответить | Цитировать Сообщить модератору
 Re: задачка на рекурсию  [new]
Ilnur26
Member

Откуда:
Сообщений: 15
f50,
Попробуйте так,
;with cte as
(
select id, pid, n, 0 as lvl, cast(pid as varchar(max)) + '|' as parents from t1 where pid = 1
union all
select t.id, t.pid, t.n, cte.lvl + 1, cte.parents + cast(t.pid as varchar(max)) + '|'
from t1 t
inner join
	cte
	on cte.id = t.pid
)
select * from cte where parents like '%|7|%'

но должно быть решение по-красивее
2 июн 17, 17:17    [20535711]     Ответить | Цитировать Сообщить модератору
 Re: задачка на рекурсию  [new]
Remind
Member

Откуда: UK
Сообщений: 523
f50,
;with cte as (
  select * 
  from t1
  where id = 7
union all
  select t1.* 
  from t1
  join cte on cte.id = t1.pid
)
select * from cte
2 июн 17, 18:02    [20535844]     Ответить | Цитировать Сообщить модератору
 Re: задачка на рекурсию  [new]
f50
Member

Откуда: Россия
Сообщений: 453
Ilnur26, спасибо за ответ!!!
А особенно огромное спасибо Remind за его компактный код! Это просто счастье какое то, сейчас сделаю нужный отчётец! Remind, счастья Вам!
3 июн 17, 22:45    [20537440]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить