我写了一个函数,它返回列表中所有项目的组合。你需要在这个函数上做一些工作才能得到“作为数据集”的结果(所以它不会只返回组合——作为列表项——而是你想看到的)。
USE [MYDB_NAME_HERE]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[ItemCombinations] (
@strSep char(1) = ';', --REQUIRED, the character to split the @List string on
@myItemList varchar(max), --REQUIRED, list of items which should be combined
@minUse int, --combine at least this number of items from the list
@maxUse int --combine at most this number of items from the list
)
RETURNS @combos TABLE (myCols varchar(max))
AS
BEGIN
IF (@myItemList = '')
RETURN
DECLARE @tmpRetVal TABLE (
unID tinyint IDENTITY(1,1) PRIMARY KEY NONCLUSTERED,
cols varchar(500),
bitV AS CONVERT (integer, POWER(2, unID - 1)) PERSISTED UNIQUE CLUSTERED
)
DECLARE @tmpRes TABLE (
colcount int NULL,
cols varchar(max)
)
INSERT INTO @tmpRetVal (cols)
SELECT * FROM dbo.StrSplit (';',@myItemList) AS cols
DECLARE @max integer = POWER (2, (SELECT COUNT(*) FROM @tmpRetVal AS tRET)) - 1;
INSERT INTO @tmpRes (cols)
SELECT combination = STUFF (( SELECT @strSep + tRET.cols
FROM @tmpRetVal AS tRET
WHERE NUM.Number & tRET.bitV = tRET.bitV
ORDER BY tRET.bitV
FOR XML PATH (''),
TYPE).value('(./text())[1]', 'varchar(8000)'), 1, 1, '')
FROM [dbo].[Numbers] AS NUM
WHERE NUM.Number BETWEEN 1 AND @max;
UPDATE @tmpRes SET colcount = (LEN(cols) - LEN(REPLACE(cols, @strSep, '')) + 1)
DELETE FROM @tmpRes WHERE (colcount @maxUse)
INSERT INTO @combos (myCols)
SELECT cols FROM @tmpRes
RETURN
END
与(例如)这个人在这里立即进行测试:
SELECT * FROM [dbo].[ItemCombinations] (';','Lady;Man;Hello',1,3)
GO
将给出这个结果集:同样,您可以修改函数以返回数据集/数据表而不是项目列表,然后您就在那里。
编辑:忘记添加我的 StrSplit 函数
Lady
Man
Lady;Man
Foo
Lady;Foo
Man;Foo
Lady;Man;Foo
USE [MYDB_NAME_HERE]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- FUNCTIONALITY: splits a [delimeter] separated string into list of items: 1 item == 1 record
-- e.g. "that;wasn't;chicken" delimetered by ";" will turn into a recordset of 3 records
-- =============================================
CREATE FUNCTION [dbo].[StrSplit] (
@strSep char(1) = ';', --REQUIRED, the character to split the @List string on
@myList varchar(max)--REQUIRED, the list to split apart
)
RETURNS @sItems TABLE (txItem varchar(10))
AS
BEGIN
IF @myList IS NULL RETURN
DECLARE @iStart int
DECLARE @iPos int
IF SUBSTRING(@myList,1,1) = @strSep
BEGIN
SET @iStart = 2
INSERT INTO @sItems
VALUES
(NULL)
END
ELSE
SET @iStart = 1
WHILE 1=1
BEGIN
SET @iPos = CHARINDEX( @strSep, @myList, @iStart )
IF @iPos = 0 SET @iPos = LEN( @myList )+1
IF @iPos - @iStart > 0
INSERT INTO @sItems
VALUES
(SUBSTRING( @myList, @iStart, @iPos-@iStart ))
ELSE
INSERT INTO @sItems
VALUES
(NULL)
SET @iStart = @iPos+1
IF @iStart > len( @myList )
BREAK
END
RETURN
END
(使用复杂的函数来展开列表,而不是因为 SQL Server 与交叉调用-SP 与函数相关的限制而更简单的 SP)