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

Откуда: СПб
Сообщений: 244
Стоит задача перебора вариантов: Каждый тип детали может обрабатываться на различных станках. Надо перебрать все варианты обработки заданного множества типов деталей.
В приведенном примере тип 100 может обрабатываться на станках 300, 301, 302, тип 105 - на станках 301, 310.

Хочется получить результат:

№ варианта Тип Станок
1 100 300
1 105 310
2 100 301
2 105 310
3 100 302
3 105 301
4 100 300
4 105 301
5 100 301
5 105 301
6 100 302
6 105 310

Естественно, есть наружные условия, ограничивающие объем (а то количество вариантов улетает в бесконечность). Предполагается, что порядок обработки неважен (сначала тип 100 на станке 301, потом тип 105 на том же станке или наоборот). Нумерация вариантов произвольная.
Сваял код, который работает, но эстетического удовольствия не доставляет. Может попробуете поизящнее?


В процессе используется таблица @Numbers, содержащая последовательные числа 1,2,3 ...
На всякий случай в примере привел ее генерацию
declare @Numbers table (IntId int)

insert into @Numbers
select ROW_NUMBER() over(order by [Name]) from sys.objects

declare @t table (a1 int,b1 int,a int,b int,c int,cc int)

insert @t(a1,b1) select 100,300 union all select 100,301 union all select 100,302
union all select 105,301 union all select 105,310

-- Собственно код
declare @Num int

;with t as
(select a2 = DENSE_RANK() over(Order by a1),b2 = DENSE_RANK() over(partition by a1 Order by b1),* from @t)

update t
set a=a2,b=b2

update t
set c =(SELECT ISNULL(exp(sum(log(c))),1) from (select COUNT(*) c FROM @t r WHERE r.a<t.a group by a)tt)
,cc = (select COUNT(*) FROM @t r2 WHERE r2.a=t.a)
FROM @t t

SELECT @Num = exp(sum(log(c)))
from (
select COUNT(*) c
FROM @t
group by a)t

select n.IntId,t.a1,t.b1
From @t t
join @Numbers n
ON (IntId/c)%cc=b%cc
where n.IntId <=@Num
order by 1,2,3
12 ноя 09, 12:12    [7919241]     Ответить | Цитировать Сообщить модератору
 Re: Код для критики  [new]
aleks2
Guest
Не оглашена целевая функция перебора вариантов, ибо если просто варианты - исчисли декартово произведение.

И будь щастлив...
12 ноя 09, 12:15    [7919272]     Ответить | Цитировать Сообщить модератору
 Re: Код для критики  [new]
remi_
Member

Откуда: СПб
Сообщений: 244
Мдя...
Не могли бы привести это самое ... декартово по примеру?
Тут задача потоньше будет.
12 ноя 09, 12:27    [7919386]     Ответить | Цитировать Сообщить модератору
 Re: Код для критики  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
remi_
Мдя...
Не могли бы привести это самое ... декартово по примеру?
Тут задача потоньше будет.
ANSI SQL89 - ,
ANSI SQL92 - CROSS JOIN
Вам может оказаться полезным INNER JOIN с нетривиальным условием в ON (в смысле не простое =)

А вообще, напрашивается таблица, связывающая тип детали и станок отношением "многие-ко-многим".

P.S. Стартовое сообщение почти не читал, поскольку неотформатировано.
12 ноя 09, 12:33    [7919455]     Ответить | Цитировать Сообщить модератору
 Re: Код для критики  [new]
aleks2
Guest
remi_
Мдя...
Не могли бы привести это самое ... декартово по примеру?
Тут задача потоньше будет.

Вот и описал бы поточнее эти тонкости... или ты предлагаешь самому придумать постановку?

select tip100.stanok, tip105.stanok, row_number() over(order by tip100.stanok) as variant
from
(select 300 stanok union all  select 301 union all select 302) tip100
CROSS JOIN
(select 310 stanok union all  select 301) tip105
12 ноя 09, 12:39    [7919518]     Ответить | Цитировать Сообщить модератору
 Re: Код для критики  [new]
aleks2
Guest
Ну или максимально приближенное к желаемому

select 100 tip ,tip100.stanok , row_number() over(order by tip100.stanok) as variant
from
(select 300 stanok union all  select 301 union all select 302) tip100
CROSS JOIN
(select 310 stanok union all  select 301) tip105
union all
select 105 tip, tip105.stanok, row_number() over(order by tip100.stanok) as variant
from
(select 300 stanok union all  select 301 union all select 302) tip100
CROSS JOIN
(select 310 stanok union all  select 301) tip105
12 ноя 09, 12:42    [7919559]     Ответить | Цитировать Сообщить модератору
 Re: Код для критики  [new]
remi_
Member

Откуда: СПб
Сообщений: 244
Миленько. Т.е. по любому конкретному варианту получается простым перечислением. А по произвольному, а то и по входной таблице из примера?

Я уж не знаю, как писать еще информативнее и чем не понравилась исходная постановка, но попробую. Принесли детали нескольких типов. По одной штуке каждого. Вариантом именуется перечень типов, обрабатываемых каждый на одном станке. Связь тип детали - станок многие ко многим. Т.е. в каждый вариант должны войти все типы по одному разу.
Далее по каждому варианту будет оцениваться эффективность и выбираться лучший и прочее и прочее, что к самой генерации вариантов отношения не имеет.

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

Откуда:
Сообщений: 104760
remi_

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

https://www.sql.ru/forum/actualthread.aspx?tid=127456 п.4 и п.6
12 ноя 09, 13:09    [7919882]     Ответить | Цитировать Сообщить модератору
 Re: Код для критики  [new]
remi_
Member

Откуда: СПб
Сообщений: 244
Glory
п.4 и п.6

п.4 - ага, стормозил SQL 2008
п.6 - мне как раз и казалось, что максимально подробно описал совсем непростую задачу. И все скрипты выложил.
12 ноя 09, 14:03    [7920450]     Ответить | Цитировать Сообщить модератору
 Re: Код для критики  [new]
Glory
Member

Откуда:
Сообщений: 104760
remi_
Glory
п.4 и п.6

п.4 - ага, стормозил SQL 2008
п.6 - мне как раз и казалось, что максимально подробно описал совсем непростую задачу. И все скрипты выложил.

Скрипты создания таблиц ? Заполнения их тестовыми данными ? Ваш пример "Хочется получить результат:" соответствует тому, какие тестовые данные вы занесли ?
12 ноя 09, 14:11    [7920533]     Ответить | Цитировать Сообщить модератору
 Re: Код для критики  [new]
remi_
Member

Откуда: СПб
Сообщений: 244
"То ли я тупой, то ли лыжи не едут" (с)

declare @t table (a1 int,b1 int,a int,b int,c int,cc int)

insert @t(a1,b1) select 100,300 union all select 100,301 union all select 100,302
union all select 105,301 union all select 105,310

На выходе хочется иметь

№ варианта Тип Станок
1 100 300
1 105 310
2 100 301
2 105 310
3 100 302
3 105 301
4 100 300
4 105 301
5 100 301
5 105 301
6 100 302
6 105 310
12 ноя 09, 14:21    [7920618]     Ответить | Цитировать Сообщить модератору
 Re: Код для критики  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
remi_,

хорошо бы ещё тегом [SRС] пользоваться!
12 ноя 09, 14:28    [7920680]     Ответить | Цитировать Сообщить модератору
 Re: Код для критики  [new]
aleks2
Guest
remi_
Миленько. Т.е. по любому конкретному варианту получается простым перечислением. А по произвольному, а то и по входной таблице из примера?


Если это не тупость, то что же это?
declare @t table (a int,b int)

insert @t(a,b)
select 100,300 union all select 100,301 union all select 100,302 
union all select 105,301 union all select 105,310 


select [100].a [тип] , [100].b [станок], row_number() over(order by [100].[станок]) as variant
from
(select * FROM @t WHERE a=100) [100]
CROSS JOIN
(select * FROM @t WHERE a=105) [105]
UNION ALL
select [105].a [тип] , [105].b [станок], row_number() over(order by [100].[станок]) as variant
from
(select * FROM @t WHERE a=100) [100]
CROSS JOIN
(select * FROM @t WHERE a=105) [105]
12 ноя 09, 17:38    [7922107]     Ответить | Цитировать Сообщить модератору
 Re: Код для критики  [new]
aleks2
Guest
Упрощенный вариант для...

declare @t table (a int,b int)

insert @t(a,b)
select 100,300 union all select 100,301 union all select 100,302 
union all select 105,301 union all select 105,310 


select t.a [тип] , t.b [станок], row_number() over(order by t.[станок]) as variant
from
@t t
CROSS JOIN
@t tt
WHERE t.a>tt.a
UNION ALL
select tt.a [тип] , tt.b [станок], row_number() over(order by t.[станок]) as variant
from
@t t
CROSS JOIN
@t tt
WHERE t.a>tt.a
13 ноя 09, 06:22    [7923519]     Ответить | Цитировать Сообщить модератору
 Re: Код для критики  [new]
remi_
Member

Откуда: СПб
Сообщений: 244
aleks2
Упрощенный вариант для...

declare @t table (a int,b int)

insert @t(a,b)
select 100,300 union all select 100,301 union all select 100,302 
union all select 105,301 union all select 105,310 


select t.a [тип] , t.b [станок], row_number() over(order by t.[станок]) as variant
from
@t t
CROSS JOIN
@t tt
WHERE t.a>tt.a
UNION ALL
select tt.a [тип] , tt.b [станок], row_number() over(order by t.[станок]) as variant
from
@t t
CROSS JOIN
@t tt
WHERE t.a>tt.a


Прошу пардону за тормоз с ответом, только сейчас смог добраться до компа.
Увы, но это решение совсем не в тему.
Это перебор всех вариантов состоящих ровно из двух строк.
А если строк должно быть другое количество?

Для примера

insert @t(a,b)
select 100,300 union all select 100,301 union all select 100,302 
или же
insert @t(a,b)
select 100,300 union all select 100,301 union all select 100,302 
union all select 105,301 
union all select 107,310

Ну не получится здесь простым CROSS JOIN :-(
19 ноя 09, 11:43    [7949535]     Ответить | Цитировать Сообщить модератору
 Re: Код для критики  [new]
aleks2
Guest
remi_,

>>Это перебор всех вариантов состоящих ровно из двух строк.
Это перебор всех вариантов состоящих ровно из двух деталей.

Ну низзя же быть таким несообразительным! Можно подумать твоя программа канает для любого количества...

Динамический SQL - forever!!!

Тем более, после того как количество типов деталей перевалит за три - тебе это уже будет ненужно... хе-хе.
19 ноя 09, 12:10    [7949798]     Ответить | Цитировать Сообщить модератору
 Re: Код для критики  [new]
remi_
Member

Откуда: СПб
Сообщений: 244
aleks2

Можно подумать твоя программа канает для любого количества...

В общем-то так оно и есть. Рабочие варианты на 10-15 деталей и 1-3 станка работают вполне адекватно.

aleks2

Динамический SQL - forever!!!

Посмотрев ваш код я об этом и задумался. Но тоже как-то неэстетично.
19 ноя 09, 13:45    [7950649]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить