I need to generate all combinations of size @k
in a given set of size @n
. Can someone please review the following SQL and determine first if the fo
First create this UDF...
CREATE FUNCTION [dbo].[_ex_fn_SplitToTable] (@str varchar(5000), @sep char(1) = null)
RETURNS @ReturnVal table (n int, s varchar(5000))
AS
/*
Alpha Test
-----------
select * from [dbo].[_ex_fn_SplitToTable_test01]('abcde','')
*/
BEGIN
declare @str2 varchar(5000)
declare @sep2 char(1)
if LEN(ISNULL(@sep,'')) = 0
begin
declare @i int
set @i = 0
set @str2 = ''
declare @char varchar(1)
startloop:
set @i += 1
--print @i
set @char = substring(@str,@i,1)
set @str2 = @str2 + @char + ','
if LEN(@str) <= @i
goto exitloop
goto startloop
exitloop:
set @str2 = left(@str2,LEN(@str2) - 1)
set @sep2 = ','
--print @str2
end
else
begin
set @str2 = @str
set @sep2 = @sep
end
;WITH Pieces(n, start, stop) AS (
SELECT 1, 1, CHARINDEX(@sep2, @str2)
UNION ALL
SELECT n + 1, stop + 1, CHARINDEX(@sep2, @str2, stop + 1)
FROM Pieces
WHERE stop > 0
)
insert into @ReturnVal(n,s)
SELECT n,
SUBSTRING(@str2, start, CASE WHEN stop > 0 THEN stop-start ELSE 5000 END) AS s
FROM Pieces option (maxrecursion 32767)
RETURN
END
GO
Then create this stored proc...
CREATE proc [CombinationsOfString]
(
@mystring varchar(max) = '0,5,10,15,20,25'
)
as
/*
ALPHA TEST
---------
exec CombinationsOfString '-20,-10,0,10,20'
*/
if object_id('tempdb..#_201606070947_myorig') is not null drop table #_201606070947_myorig
CREATE TABLE #_201606070947_myorig
(
SourceId int not null identity(1,1)
,Element varchar(100) not null
)
insert into #_201606070947_myorig
select s from dbo._ex_fn_SplitToTable(@mystring,',')
--select SourceId, Element from #_201606070947_myorig
declare @mynumerics varchar(max)
set @mynumerics = (
select STUFF(REPLACE((SELECT '#!' + LTRIM(RTRIM(SourceId)) AS 'data()'
FROM #_201606070947_myorig
FOR XML PATH('')),' #!',', '), 1, 2, '') as Brands
)
set @mynumerics = REPLACE(@mynumerics,' ','')
print @mynumerics
if object_id('tempdb..#_201606070947_source') is not null drop table #_201606070947_source
if object_id('tempdb..#_201606070947_numbers') is not null drop table #_201606070947_numbers
if object_id('tempdb..#_201606070947_results') is not null drop table #_201606070947_results
if object_id('tempdb..#_201606070947_processed') is not null drop table #_201606070947_processed
CREATE TABLE #_201606070947_source
(
SourceId int not null identity(1,1)
,Element char(1) not null
)
--declare @mynumerics varchar(max)
--set @mynumerics = '1,2,3,4,5'
insert into #_201606070947_source
select s from dbo._ex_fn_SplitToTable(@mynumerics,',')
-- select * from #_201606070947_source
declare @Length int
set @Length = (select max(SourceId) from #_201606070947_source)
declare @columnstring varchar(max) = (SELECT REPLICATE('c.',@Length))
print @columnstring
declare @subs varchar(max) = (SELECT REPLICATE('substring.',@Length))
print @subs
if object_id('tempdb..#_201606070947_columns') is not null drop table #_201606070947_columns
select s+CONVERT(varchar,dbo.PadLeft(convert(varchar,n),'0',3)) cols
into #_201606070947_columns
from [dbo].[_ex_fn_SplitToTable](@columnstring,'.') where LEN(s) > 0
if object_id('tempdb..#_201606070947_subcolumns') is not null drop table #_201606070947_subcolumns
select s+'(Combo,'+CONVERT(varchar,n)+',1) ' + 'c'+CONVERT(varchar,dbo.PadLeft(convert(varchar,n),'0',3)) cols
into #_201606070947_subcolumns
from [dbo].[_ex_fn_SplitToTable](@subs,'.') where LEN(s) > 0
-- select * from #_201606070947_subcolumns
-- select * from #_201606070947_columns
declare @columns_sql varchar(max)
set @columns_sql =
(
select distinct
stuff((SELECT distinct + cast(cols as varchar(50)) + ' VARCHAR(1), '
FROM (
select cols
from #_201606070947_columns
) t2
--where t2.n = t1.n
FOR XML PATH('')),3,0,'')
from (
select cols
from #_201606070947_columns
) t1
)
declare @substring_sql varchar(max)
set @substring_sql =
(
select distinct
stuff((SELECT distinct + cast(cols as varchar(100)) + ', '
FROM (
select cols
from #_201606070947_subcolumns
) t2
--where t2.n = t1.n
FOR XML PATH('')),3,0,'')
from (
select cols
from #_201606070947_subcolumns
) t1
)
set @substring_sql = left(@substring_sql,LEN(@substring_sql) - 1)
print @substring_sql
set @columns_sql = LEFT(@columns_sql,LEN(@columns_sql) - 1)
--SELECT @columns_sql
declare @sql varchar(max)
set @sql = 'if object_id(''tempdb..##_201606070947_01'') is not null drop table ##_201606070947_01 create table ##_201606070947_01 (rowid int,' + @columns_sql + ')'
print @sql
execute(@sql)
CREATE TABLE #_201606070947_numbers (Number int not null)
insert into #_201606070947_numbers
select SourceId from #_201606070947_source
CREATE TABLE #_201606070947_results
(
Combo varchar(10) not null
,Length int not null
)
SET NOCOUNT on
DECLARE
@Loop int
,@MaxLoop int
-- How many elements there are to process
SELECT @MaxLoop = max(SourceId)
from #_201606070947_source
-- Initialize first value
TRUNCATE TABLE #_201606070947_results
INSERT #_201606070947_results (Combo, Length)
select Element, 1
from #_201606070947_source
where SourceId = 1
SET @Loop = 2
-- Iterate to add each Element after the first
WHILE @Loop <= @MaxLoop
BEGIN
INSERT #_201606070947_results (Combo, Length)
select distinct
left(re.Combo, @Loop - nm.Number)
+ so.Element
+ RIGHT(re.Combo, nm.Number - 1)
,@Loop
from #_201606070947_results re
inner join #_201606070947_numbers nm
on nm.Number <= @Loop
inner join #_201606070947_source so
on so.SourceId = @Loop
where re.Length = @Loop - 1
SET @Loop = @Loop + 1
END
-- select * from #_201606070947_results
-- Show #_201606070947_results
SELECT *
into #_201606070947_processed
from #_201606070947_results
where Length = @MaxLoop
order by Combo
-- select * from #_201606070947_processed
set @sql = 'if object_id(''tempdb..##_201606070947_02'') is not null drop table ##_201606070947_02 '
print @sql
execute(@sql)
set @sql = ' ' +
' SELECT ROW_NUMBER() OVER(ORDER BY Combo Asc) AS RowID,' + @substring_sql +
' into ##_201606070947_02 ' +
' FROM #_201606070947_processed ' +
' '
PRINT @sql
execute(@sql)
declare @columns_sql_new varchar(max)
set @columns_sql_new = REPLACE(@columns_sql,'(1)','(100)')
set @sql = 'if object_id(''tempdb..##_201606070947_03'') is not null drop table ##_201606070947_03 create table ##_201606070947_03 (RowId int,' + @columns_sql_new + ')'
PRINT @sql
execute(@sql)
insert into ##_201606070947_03 (RowId)
select RowId from ##_201606070947_02
--select * from ##_201606070947_03
DECLARE @ColumnId varchar(10)
DECLARE @getColumnId CURSOR
SET @getColumnId = CURSOR FOR
select cols ColumnId from #_201606070947_columns
OPEN @getColumnId
FETCH NEXT
FROM @getColumnId INTO @ColumnId
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @ColumnId
set @sql = ' ' +
' update ##_201606070947_03
set ' + @ColumnId + ' = B.Element
from ##_201606070947_03 A
, (
select A.RowID, B.*
from
(
select * from ##_201606070947_02
) A
,
(
select * from #_201606070947_myorig
) B
where A.' + @ColumnId + ' = B.SourceId
) B
where A.RowId = B.RowId
'
execute(@sql)
print @sql
FETCH NEXT
FROM @getColumnId INTO @ColumnId
END
CLOSE @getColumnId
DEALLOCATE @getColumnId
select * from ##_201606070947_03