Как построить 2 ^ N измененного слова из слова с длиной N в SQL Server - PullRequest
7 голосов
/ 21 декабря 2011

Мне нужна функция на сервере sql для построения всех измененных слов в следующем примере;для входного слова длиной n необходимо построить 2 ^ n измененного слова;Например, если вход функции

"I"

, то выход функции должен быть

I
-   

, вход функции

"am"

вывод функции должен быть

am
-m
a-
--

вход функции

"sql"

вывод функции должен быть

sql
-ql
s-l
sq-
--l
s--
-q-
--- 

Ответы [ 2 ]

9 голосов
/ 21 декабря 2011

Вы можете сделать это с таблицей чисел (master..spt_values) и stuff в цикле.

declare @Word varchar(10) = 'sql'

declare @T table
(
  Word varchar(10)
)

insert into @T values (@Word)

while not exists(select *
                 from @T 
                 where Word = replicate('-', len(@Word)))
begin              
  insert into @T(Word)
  select distinct stuff(T.Word, N.number, 1, '-')
  from @T as T
    cross join
       master..spt_values as N
  where N.type = 'P' and
        N.number between 1 and len(@Word) and
        stuff(T.Word, N.number, 1, '-') not in (select Word from @T)
end        

select *
from @T

https://data.stackexchange.com/stackoverflow/q/122334/

ИлиВы можете использовать рекурсивный CTE

declare @Word varchar(10) = 'sql'

;with C as
(
  select @Word as Word,
         0 as Iteration
  union all
  select cast(stuff(Word, N.number, 1, '-') as varchar(10)),
         Iteration + 1
  from C
    cross join
       master..spt_values as N
  where N.type = 'P' and
        N.number between 1 and len(@Word) and
        Iteration < len(@Word)
)
select distinct Word
from C

https://data.stackexchange.com/stackoverflow/q/122337/

Обновление

Рекурсивная версия CTE действительно медленная, как указано OP вкомментарий.Используя слово из 7 букв, из CTE возвращается 960800 строк.

6 голосов
/ 21 декабря 2011

Этот рекурсивный CTE

declare @input varchar(25)

set @input = 'SQL'
;WITH cte 
     AS (SELECT Stuff(@input, v.NUMBER, 1, '-') OUTPUT, 
                0                               LEVEL 
         FROM   MASTER..spt_values v 
         WHERE  TYPE = 'P' 
                AND NUMBER BETWEEN 1 AND Len(@input) 
         UNION ALL 
         SELECT Stuff(cte.OUTPUT, v.NUMBER, 1, '-') OUTPUT, 
                cte.LEVEL + 1                       AS LEVEL 
         FROM   MASTER..spt_values v, 
                cte 
         WHERE  TYPE = 'P' 
                AND cte.LEVEL + 1 < Len(@input) 
                AND NUMBER BETWEEN 1 AND Len(@input)) SELECT DISTINCT OUTPUT 
FROM   cte 
UNION 
SELECT @INPUT 
ORDER  BY OUTPUT 

производит следующий вывод

---    
--l    
-q-    
-ql    
s--    
s-l    
sq-    
sql

Я оставляю это вам, чтобы ввести в функцию.

Посмотрите, как работает этот запрос data.se

...