2014-08-28 46 views
1

的排序顺序和值的每个组合如果非要用逗号分隔的数字字符串,像这样:得到一个CSV

Declare @string varchar(20) = '123,456,789' 

,并想通过返回值的每个可能的组合+排序这样做:

Select Combination FROM dbo.GetAllCombinations(@string) 

这将在返回结果是:

123 
456 
789 
123,456 
456,123 
123,789 
789,123 
456,789 
789,456 
123,456,789 
123,789,456 
456,789,123 
456,123,789 
789,456,123 
789,123,456 

正如你看到的,不仅是每个组合都会返回,还包括每个组合+排序顺序。该示例仅示出了3由逗号分隔的值,但应该解析的任何量 - 递归。

将是使用WITH CUBE语句的境界某处所需要的逻辑,但使用WITH CUBE(表中的结构,而不是当然的CSV)的问题,就是它不会洗牌值123,456 456,123 etc.的顺序,并且只会提供每个组合,这只是战斗的一半。

目前我不知道该怎么尝试。如果有人可以提供一些援助,将不胜感激。

+4

http://dba.stackexchange.com/questions/29661/sql-query-for-combinations-without-repetition – Donal 2014-08-28 01:19:36

+0

排列是你正在寻找的词我认为:) https://www.google.com .au/webhp?sourceid = chrome-instant&ion = 1&espv = 2&ie = UTF-8#q = define%3Apermutation – 2014-08-28 01:27:29

+0

谢谢@Donal那完美无缺。不幸的是它需要的时间太长了,我即使使用CLR。虽然值得一试。 – 2014-08-28 07:35:41

回答

0

我使用了一个名为split_delimiter的用户定义的表值函数,它有两个值:@delimited_string和@delimiter_type。

CREATE FUNCTION [dbo].[split_delimiter](@delimited_string VARCHAR(8000), @delimiter_type CHAR(1)) 
RETURNS TABLE AS 
RETURN 
WITH cte10(num) AS 
(
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 
)       
,cte100(num) AS 
(
    SELECT 1 
    FROM cte10 t1, cte10 t2 
) 
,cte10000(num) AS 
(
    SELECT 1 
    FROM cte100 t1, cte100 t2 
) 
,cte1(num) AS 
(
    SELECT TOP (ISNULL(DATALENGTH(@delimited_string),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) 
    FROM cte10000 
) 
,cte2(num) AS 
(
    SELECT 1 
    UNION ALL 
    SELECT t.num+1 
    FROM cte1 t 
    WHERE SUBSTRING(@delimited_string,t.num,1) = @delimiter_type 
) 
,cte3(num,[len]) AS 
(
    SELECT t.num 
      ,ISNULL(NULLIF(CHARINDEX(@delimiter_type,@delimited_string,t.num),0)-t.num,8000) 
    FROM cte2 t 
) 

SELECT delimited_item_num = ROW_NUMBER() OVER(ORDER BY t.num) 
     ,delimited_value = SUBSTRING(@delimited_string, t.num, t.[len]) 
FROM cte3 t; 

使用,我是能够到CSV解析到一个表,并多次参加回本身并使用WITH ROLLUP得到你正在寻找的排列。

WITH Numbers as 
(
SELECT  delimited_value 
FROM  dbo.split_delimiter('123,456,789',',') 
) 

SELECT  CAST(Nums1.delimited_value AS VARCHAR) 
      ,ISNULL(CAST(Nums2.delimited_value AS VARCHAR),'') 
      ,ISNULL(CAST(Nums3.delimited_value AS VARCHAR),'') 
      ,CAST(Nums4.delimited_value AS VARCHAR) 
FROM  Numbers as Nums1 
LEFT JOIN Numbers as Nums2 
    ON  Nums2.delimited_value not in (Nums1.delimited_value) 
LEFT JOIN Numbers as Nums3 
    ON  Nums3.delimited_value not in (Nums1.delimited_value, Nums2.delimited_value) 
LEFT JOIN Numbers as Nums4 
    ON  Nums4.delimited_value not in (Nums1.delimited_value, Nums2.delimited_value, Nums3.delimited_value) 
GROUP BY CAST(Nums1.delimited_value AS VARCHAR) 
      ,ISNULL(CAST(Nums2.delimited_value AS VARCHAR),'') 
      ,ISNULL(CAST(Nums3.delimited_value AS VARCHAR),'') 
      ,CAST(Nums4.delimited_value AS VARCHAR) WITH ROLLUP 

如果您可能有超过3个或4个,则需要相应地扩展您的代码。