リスト内のアイテムのすべての組み合わせを返す関数を作成しました。結果を「データセットとして」取得するには、この関数で少し作業する必要があります (したがって、リスト項目としてのみ組み合わせを返すのではなく、見たいものを返します)。
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と関数-)