2017-04-21 8 views
0

データの各行ごとに固有の3文字の文字列(テキストと数値が可能)を生成する必要がありますすでに別のテーブルに存在しています。コードが別のテーブルに存在しないときに各行ごとに一意の文字列を生成

新しい列はデータベースに格納されず、オンデマンドで生成する必要があります。

私が使っていた:

SELECT Name, SurName,UNQCode =LEFT(NEWID(),3) 
FROM Table 

結果:

Name SurName UNQCode 
George Colon  781 
Robert Studer  297 
Thomas White  A44 

形式で結構ですが、私は、生成されたコードは、別のテーブルに存在しないことを保証する必要があります。

Select Code from Table123 

結果:

Code 
177 
21F 
585 
63C 
696 
9EF 
DA4 
056 
+0

3文字コードはそれほどありません!多くの人よりも少ないです。 – Jodrell

+0

十分な50kの組み合わせがあります – attention

+1

潜在的な反復回数が増えるにつれて、新しいユニークな値を生成する50kに近づくにつれて、問題はますます問題になります。壁に当たったら、無限ループに終わることができます。本当にこの方法を使いたいのであれば、最初に利用可能な値の表を作成し、それを使用するときにその行を削除してください。 –

答えて

0

あなたはthe code

CREATE TABLE #Char 
(
    [Value] CHAR(1) 
); 

CREATE TABLE Codes 
(
    [Code] CHAR(3) 
); 

INSERT #Char 
VALUES 
('0'), 
('1'), 
('2'), 
('3'), 
('4'), 
('5'), 
('6'), 
('7'), 
('8'), 
('9'), 
('A'), 
('B'), 
('C'), 
('D'), 
('E'), 
('F'), 
('G'), 
('H'), 
('I'), 
('J'), 
('K'), 
('L'), 
('M'), 
('N'), 
('O'), 
('P'), 
('Q'), 
('R'), 
('S'), 
('T'), 
('U'), 
('V'), 
('W'), 
('X'), 
('Y'), 
('Z'); 

INSERT Codes 
SELECT 
     T.[Code] 
    FROM 
     (SELECT 
       A.[Value] + B.[Value] + C.[Value] [Code] 
      FROM 
       #Char A 
      CROSS JOIN 
       #Char B 
      CROSS JOIN 
       #Char C) T 
    ORDER BY 
     RAND(); 

SELECT COUNT([Code]) FROM [Codes]; 

を考慮すればあなたは正確に46656順列があることがわかります。

今、あなたはすべての可能な順列のテーブルを持っていることをあなたはこのようなすべての未使用コードを取得することができます、

SELECT [Code] FROM [Codes] 
EXCEPT 
SELECT [Code] FROM [Table123] 

ベア心​​の中で、[Table123]が大きくなるにつれて、これはあなたの呼び出しの多くを救うことNEWID()のように、文字通り、最初の3文字が同じ数十億のユニークIDがあるためです。

[コード]テーブルには、コードが使用されているかどうかを示すビットフィールドを追加するなど、コード割り当てのパフォーマンスを最適化するためにできることがたくさんあります。

+0

ありがとう!私はこれを使用することができた – attention

0

約50kの組み合わせで十分ですか?

DECLARE @table1 TABLE (code CHAR(3)); 
--Pre-load five code values that we don't want to see again 
INSERT INTO @table1 SELECT LEFT(NEWID(), 3); 
INSERT INTO @table1 SELECT LEFT(NEWID(), 3); 
INSERT INTO @table1 SELECT LEFT(NEWID(), 3); 
INSERT INTO @table1 SELECT LEFT(NEWID(), 3); 
INSERT INTO @table1 SELECT LEFT(NEWID(), 3); 
DECLARE @table2 TABLE (name VARCHAR(255)); 
--Put in a couple of names 
INSERT INTO @table2 SELECT 'John Smith'; 
INSERT INTO @table2 SELECT 'Mary Stuart'; 
WITH NewCodes AS (
    SELECT 1 AS row_id, LEFT(NEWID(), 3) AS code 
    UNION ALL 
    SELECT row_id + 1 AS row_id, LEFT(NEWID(), 3) AS code FROM NewCodes nc WHERE row_id <= 50000), 
DistinctCodes AS (
    SELECT DISTINCT code FROM NewCodes), 
UniqueCodes AS (
    SELECT 
     dc.code, 
     ROW_NUMBER() OVER (ORDER BY NEWID()) AS row_id 
    FROM 
     DistinctCodes dc 
     LEFT JOIN @table1 t1 ON t1.code = dc.code 
    WHERE 
     t1.code IS NULL), 
Names AS (
    SELECT 
     name, 
     ROW_NUMBER() OVER (ORDER BY name) AS row_id 
    FROM 
     @table2 t2) 
SELECT 
    n.name, 
    uc.code 
FROM 
    Names n 
    INNER JOIN UniqueCodes uc ON uc.row_id = n.row_id OPTION (MAXRECURSION 0); 

それは実際には非常に興味深い問題だし、一つの非セットが必要な場合があります:

は、さてあなたは、(私はあなたが実際にこのような何かを行うことを推奨しておりません注意してください)このような何かを行うことができますベースのアプローチ。私はあなたがこれをループで簡単にやり遂げる方法を見ることができますが、とにかくセットベースのアプローチで刺すと思っていました。本質的に問題は、「コードを複製せずに、過去に使用されたコードを再利用することなく、名前を実現するために必要な新しいランダムコードの数」です。

関連する問題