3

指定された文字セットのすべての可能な順列を生成するために、以下のスクリプトを作成しました。

実行時に長さを指定できるようにしながら、これを効率的に行う方法はありますか?

DECLARE @string NVARCHAR(MAX)
SELECT @string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';

DECLARE @Chars TABLE (
    C CHAR(1) PRIMARY KEY
)

DECLARE @N INT 
SET @N = 1 
WHILE @N <= LEN(@string) BEGIN
    INSERT @Chars (
        C
    ) VALUES (
        SUBSTRING(@string, @N, 1)
    )

    SET @N = @N + 1
END

--SELECT * FROM @Chars


SELECT
    A.C + B.C + C.C
FROM @Chars A, @Chars B, @Chars C
ORDER BY
    A.C,
    B.C,
    C.C
4

2 に答える 2

2

SQL Server 2005 以降のバージョンを使用している場合は、再帰的な CTE を試すことができます。

DECLARE @length int;
SET @length = 3;

WITH expanded AS (
  SELECT
    C = SUBSTRING(@string, N, 1)
  FROM numbers
  WHERE number BETWEEN 1 AND LEN(@string)
),
permutations AS (
  SELECT
    S = CAST(C AS nvarchar(max)),
    L = 1
  FROM expanded
  UNION ALL
  SELECT
    S = S + C,
    L = L + 1
  FROM permutations p
  CROSS JOIN expanded e
  WHERE L < @length
)
SELECT *
FROM permutations
WHERE L = @length
;

これnumbersは、文字列を単一文字の列に展開するために使用される数値の補助テーブルです。

これ以上変更しなければ、このクエリは@length100 までの値で問題なく動作します。より長い順列が必要な場合は、次の行を追加する必要があります。

OPTION (MAXRECURSION n)

ここnで、 は再帰 CTE の最大反復回数を示す 0 ~ 32767 の整数値で、上記の 100 がデフォルトです。Nil は実際には制限がないことを意味するため、注意して使用する必要があります。

SQL Fiddleでこのクエリを試して (そして遊んで) 、 を 8 文字に減らし(クエリで多くの行を返すことなく、@stringより多くの異なる値を指定できるようにするため)、テーブルを として定義することもできます。システム テーブルのサブセット。@lengthnumbersmaster..spt_values

于 2012-07-18T20:34:03.020 に答える
0

可能な順列の数に関するコメントを受け取った後、文字セットの長さと指定された長さには非常に厳しい制限があるはずだと気づきました。

許容される長さが非常に短いことを考えると、スクリプトで条件を使用しても害はありません...次のようになります。

DECLARE
    @string NVARCHAR(40), --limit the length of the character set to 40
    @length INT -- the limit for this is in a validation check below

SELECT
    @string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',
    @length = 2



IF (@length < 1 OR @length > 4) BEGIN
    RAISERROR('Invalid length specified. This function only supports lengths from 1 to 4', 16, 1)
END



DECLARE @Chars TABLE (
    C CHAR(1) PRIMARY KEY
)

;WITH numbers AS (
    SELECT TOP(LEN(@string)) number
    FROM master..spt_values
    WHERE type = 'P'
    AND number != 0
)

INSERT @Chars (
    C
)
SELECT
    C = SUBSTRING(@string, number, 1)
FROM numbers


IF (@length = 1) BEGIN
    SELECT C FROM @Chars ORDER BY C
END ELSE IF (@length = 2) BEGIN
    SELECT A.C + B.C
    FROM @Chars A, @Chars B
    ORDER BY A.C, B.C
END ELSE IF (@length = 3) BEGIN
    SELECT A.C + B.C + C.C
    FROM @Chars A, @Chars B, @Chars C
    ORDER BY A.C, B.C, C.C
END ELSE IF (@length = 4) BEGIN
    SELECT A.C + B.C + C.C + D.C
    FROM @Chars A, @Chars B, @Chars C, @Chars D
    ORDER BY A.C, B.C, C.C, D.C
END
于 2012-07-18T21:40:04.923 に答える