2014-08-28 61 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個,則需要相應地擴展您的代碼。