2016-09-15 2 views
1

전체 커서 기반에서 집합 기반으로 코드 묶음을 이동하여 생성했습니다.이 코드는 내 머리말을하고 있습니다. 각 회사에 대해 (고유 한) 6 자의 단축 코드를 만듭니다. 데이터베이스와 내가 커서 (커서) 외부에서 이것을 달성하기를 원한다. 내가 지금까지에 나는 어디고유 한 식별자를 집합 기반 쿼리로 생성

예 :

CREATE TABLE #customers (name VARCHAR(50), shortname VARCHAR(10)) 
INSERT INTO #customers VALUES 
('Michael Smith', 'Michae') 
,('Michael Douglas', 'Mich_1') 
,('Michael Yang', 'Mich_2') 

CREATE TABLE #newcustomers (name VARCHAR(50), shortname VARCHAR(10) NULL) 
INSERT INTO #newcustomers (name) VALUES 
('Michael Black') 
,('Michael White') 

SELECT * FROM #customers 
SELECT * FROM #newcustomers 

DECLARE @shortname VARCHAR(10) 
DECLARE @iteration INT = 0 

WHILE EXISTS(SELECT shortname FROM #customers WHERE shortname = @shortname) 
BEGIN 
    SELECT @shortname = LEFT(name, 6) FROM #newcustomers 

    UPDATE #newcustomers SET shortname = @shortname 

    SET @shortname = LEFT(@shortname, 4) + '_' + @iteration 

    SET @iteration = @iteration + 1 
END 

는 희망의 예는 내가에 도착하려고 어디에, 어떤 제안이나 예는 매우 도움이 될 것입니다 확인하는데 충분하다. 내보기가 작동하지 않습니다.

+1

그냥'WHILE' 것 또한 메모, 등을 얻을 그대로 6 편지를 얻을 커서로 실행된다. 그것은 같은 구현체를 사용할 것이고, 그것은 단지 WHILE 형태로 가려져 있습니다. –

+0

'Micahel Douglas'에 오타가 있습니다. – Shnugo

+0

Btw : 좋은 질문입니다. 특히 copy'n'pasteable 테스트 시나리오가 훌륭합니다. 자신의 노력, 명확한 설명 ... +1 – Shnugo

답변

2

모형

CREATE TABLE #customers (ID INT IDENTITY, name VARCHAR(50), shortname VARCHAR(10)) 
INSERT INTO #customers VALUES 
('Michael Smith', 'Michae') 
,('Michael Douglas', 'Mich_1') 
,('Michael Yang', 'Mich_3') 
,('Testman', 'Testma') 
,('Testman1', 'Test_1'); 

CREATE TABLE #newcustomers (ID INT IDENTITY,name VARCHAR(50), shortname VARCHAR(10) NULL) 
INSERT INTO #newcustomers (name) VALUES 
('Michael Black') 
,('Michael White') 
,('Testman2') 
,('Someone new'); 

--This CTE는 기존의 모든 이름

결합합니다
WITH AllNames AS 
(
    SELECT '1_old' AS datasource,ID,name,shortname FROM #customers 
    UNION ALL SELECT '2_new',ID,name,shortname FROM #newcustomers 
) 

--This CTE가 결합 된 목록을 사용하므로이

테이블을보십시오 올바른 "색인"을 계산하십시오

,ShortNames AS 
(
    SELECT c.* 
      ,A.First6 
      ,ROW_NUMBER() OVER(PARTITION BY A.First6 ORDER BY datasource,ID) AS NrTotal 
      ,ROW_NUMBER() OVER(PARTITION BY datasource,A.First6 ORDER BY datasource,ID) AS Nr 
      ,CASE WHEN ISNUMERIC(SUBSTRING(shortname+'  ',6,10))=1 
       THEN CAST(SUBSTRING(shortname+'  ',6,10) AS INT) ELSE 0 END AS ExistIndex 
    FROM AllNames AS c 
    CROSS APPLY(SELECT LEFT(name + '  ',6)) AS A(First6) 
) 

--all NrTotal 새로운 = 1, 다른 모든 인덱스

SELECT * 
     ,CASE WHEN datasource='1_old' THEN shortname ELSE 
     CASE WHEN datasource='2_new' AND NrTotal=1 THEN First6 
      ELSE LEFT(First6,4) + '_' + CAST(Nr + (SELECT ISNULL(MAX(x.ExistIndex),1) 
                 FROM ShortNames AS x 
                 WHERE x.First6=ShortNames.First6) AS VARCHAR(5)) 
     END 
     END 
FROM ShortNames 

GO 
DROP TABLE #customers; 
DROP TABLE #newcustomers; 

에게 그 결과

+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+ 
| datasource | ID | name   | shortname | First6 | NrTotal | Nr | ExistIndex | (Kein Spaltenname) | 
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+ 
| 1_old  | 1 | Michael Smith | Michae | Michae | 1  | 1 | 0   | Michae    | 
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+ 
| 1_old  | 2 | Michael Douglas | Mich_1 | Michae | 2  | 2 | 1   | Mich_1    | 
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+ 
| 1_old  | 3 | Michael Yang | Mich_3 | Michae | 3  | 3 | 3   | Mich_3    | 
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+ 
| 1_old  | 4 | Testman   | Testma | Testma | 1  | 1 | 0   | Testma    | 
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+ 
| 1_old  | 5 | Testman1  | Test_1 | Testma | 2  | 2 | 1   | Test_1    | 
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+ 
| 2_new  | 1 | Michael Black | NULL  | Michae | 4  | 1 | 0   | Mich_4    | 
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+ 
| 2_new  | 2 | Michael White | NULL  | Michae | 5  | 2 | 0   | Mich_5    | 
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+ 
| 2_new  | 4 | Someone new  | NULL  | Someon | 1  | 1 | 0   | Someon    | 
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+ 
| 2_new  | 3 | Testman2  | NULL  | Testma | 3  | 1 | 0   | Test_2    | 
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+ 
+0

이것은 놀랍도록 완료되었습니다! 나는 경외심에 서있다! 예를 들어 'Mich_2'(마이클 양을 'Mich_3'으로 변경)가 누락되어 실행하면 ROW_NUMBER에서 벗어나 복제본이 생성됩니다.효과적으로 실행될 때마다 숫자를 재발행하여 원래의 증분을 완전히 무시합니다. –

+0

@BrianRamsey, 내 업데이트 참조 – Shnugo

+0

놀라운 ... 말문이 ... 실제로 원래 코드로 동일한 작업을 수행하려고했지만 어딘가에 있지만 당신만큼 빨리. 당신의 노력에 대해 충분히 감사 할 수 없습니다. 고맙습니다! –

0

하나의 옵션은 computed column을 사용하는 것입니다.

다음 행과 함께 테이블 디자인 일 것입니다 :

- Sample table. 
DECLARE @Sample TABLE 
    (
     Id   INT IDENTITY(1, 1), 
     FullName VARCHAR(255), 
     ShortName AS LEFT(FullName, 4) + '_' + CAST(Id AS VARCHAR(255)) 
    ) 
; 

-- Add set containing two companies. 
INSERT INTO @Sample 
    (
     FullName 
    ) 
VALUES 
    ('ABC LTD'), 
    ('XYZ PLC') 
; 

반환

Id FullName ShortName 
1 ABC LTD  ABC _1 
2 XYZ PLC  XYZ _1 

IdShortName

SQL Server에서 관리됩니다. FullName 만 추가하면됩니다. 쉽게 연주 할 수 있도록, 테이블 변수를 사용하여

편집

재 예.

+0

가치가 있습니다. 불행히도이 방법은 'ABC _1, XYZ _2'를해라. 현재 시스템의 행동 때문에'ABC _1, XYZ _1'이 필요하다. 또한 현재의 행동 때문에 첫 번째 항목은 항상 LEFT 6이되어야합니다. –

+0

Ahh 알 수 있습니다. @RaduGheorghiu 솔루션과 [윈도우 행 수] (https://msdn.microsoft.com/en-GB/library/ms186734.aspx?f=255&MSPPError=-2147217396)를 결합 할 수 있습니다. –

관련 문제