生成唯一标识符作为基于集的查询

时间:2016-09-15 08:30:19

标签: sql-server tsql data-partitioning

我正在将一堆代码从完全基于光标的基础上移动到基于集合并生成这一直在我的脑袋里。我们为插入数据库的每个公司创建一个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

希望这个例子足以确定我想要去的地方,任何建议或例子都会非常有用。我的例子不起作用。

2 个答案:

答案 0 :(得分: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');

- 此CTE将结合所有现有名称

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

- 此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)
)

- 所有新的NrTotal = 1得到6个字母,其他所有得到索引

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             |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+

答案 1 :(得分: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

修改

使用表变量重写示例,以便更轻松地进行播放。