如何在sql server中从长度为n的单词构建2 ^ n更改单词

时间:2011-12-21 06:23:00

标签: sql sql-server string sql-server-2008 tsql

我需要在sql server中使用一个函数来构建下面示例中的所有更改的单词; 对于长度为n的输入字必须构建2 ^ n改变的字;  例如,如果函数的输入是

"I"

函数的输出应为

I
-   

该功能的输入是

"am"

函数的输出应为

am
-m
a-
--

该功能的输入是

"sql"

函数的输出应为

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

2 个答案:

答案 0 :(得分:9)

您可以使用数字表(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

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

或者您可以使用reqursive 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

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

<强>更新

正如OP在评论中指出的那样,递归CTE版本非常慢。使用带有7个字母的单词,CTE返回了960800行。

答案 1 :(得分:6)

此递归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 query