2016-07-26 36 views
3

我需要将数据从列截断为10个字符。但是,我不能有任何重复项,所以我希望重复项以〜1结尾,第一个重复项以〜2结尾。这里是什么,我有一个例子:T-SQL截断文本并在末尾添加数字以避免重复

Column 
------ 
The ABC Company Inc. 
The ABC Cooperative 
XYZ Associates LLC. 

我希望得到的结果是:

Column 
------ 
The ABC ~1 
The ABC ~2 
XYZ Associ 

结束并不必须〜1〜2,我只是需要一些东西来截断后使其独特。截断后可能有3或4个以上的副本。

到目前为止,我只是截取并手动编辑表:

update Table set Column = Left(Column, 10) where len(Column) > 10 
+0

如果截断 “ABC公司公司”和“ABC合作社”共10个字符,这两个都会留下“The ABC Co”,导致重复。 – Peter

+1

ABC〜1 IS 10个字符 – AntDC

+2

如果有10个或更多重复记录,该怎么办? – datagod

回答

4

首先,你所关心的前8个字符,而不是前10 ,因为您需要为附加号码预留插槽。

假设你有少于10次重复,你可以这样做:

with toupdate as (
     select t.*, 
      row_number() over (partition by left(col, 8) order by (select null)) as seqnum, 
      count(*) over (partition by left(col, 8)) as cnt 
     from t 
update toupdate 
    set col = (case when cnt = 1 then left(col, 10) 
        else left(col, 8) + '~' + cast(seqnum as char(1)); 

同样的想法可以用于select

+1

值得注意的是,编号不能保证稳定,并且如果添加或删除行,编号很可能会改变。这并不是错的,但它可能会在稍后的某个日子让OP感到意外。 – HABO

+0

这看起来像我需要的东西。我试图修改这个查询,但是我遇到了第一行'with toupdate as'有问题。我是否支持在此代码中添加其他内容?我用我想更新的表替换了'toupdate'。 SQL管理工作室说,从't'附近有一个语法错误,不确定如何解决这个问题... – Peter

+1

@Peter。 。 。表格在'from'和't'之间的'from'子句中。 –

4
Declare @Table Table (Column1 varchar(50)) 
Insert into @Table values 
('The ABC Company Inc.'), 
('The ABC Cooperative'), 
('XYZ Associates LLC.') 

Select NewColumn = Concat(substring(Column1,1,10),' ~',Row_Number() over (Partition By substring(Column1,1,10) Order by Column1)) 
From @Table 

返回

NewColumn 
The ABC Co ~1 
The ABC Co ~2 
XYZ Associ ~1 
+0

正如Gordon提到的那样,10可能是8 –

1

的数字是嘈杂的,所以我只在必要时添加它们:

select case when _r > 1 
    then Company + '~' + cast(_r as varchar(5)) 
    else Company end as Company 
from (
    select Company 
     , ROW_NUMBER() over (partition by Company order by Company) as _r 
    from(
     select left(Company, 10) as Company 
     from MyTable 
    ) x 
) y 
order by Company 


Company 
-------------- 
The ABC Co 
The ABC Co~2 
XYZ Associ 
+0

我喜欢这个解决方案,但是如何使用它来更新我现有的表格?我无法将新表添加到此数据库,这种查询有所帮助,但我仍然需要即时更新表。 – Peter

0

假设你的表是公司和场公司名称..... 你必须tweek但希望它有助于..

SELECT SUBSTRING(Q.Comp, 1, 5) + '~' + CONVERT(nvarchar(4), Row) as NewFieldValue FROM 
(
SELECT ROW_NUMBER() OVER(PARTITION BY SUBSTRING(C.CompanyName, 1, 6) ORDER BY SUBSTRING(C.CompanyName, 1, 6)) AS Row, 
SUBSTRING(C.CompanyName, 1, 6) as Comp 
FROM COMPANY C 
)Q 
0
DECLARE @Table TABLE (Column1 varchar(50)) 

INSERT INTO @Table VALUES 
     ('The ABC Company Inc.') 
    , ('The ABC Cooperative') 
    , ('XYZ Associates LLC.') 
    , ('Acme') 
    , ('Ten Char 123') 
    , ('Ten Char 132') 
    , ('Ten Char 231') 


;WITH FLen 
    AS (
     SELECT Column1, LEFT(LEFT(Column1,13) + SPACE(13),13) + CHAR(164) AS Column2 
      FROM @Table 
     ) 

,TenCharPD -- Includes possible duplicates 
    AS (
     SELECT Column1, LEFT(Column2,8) + 
      RIGHT('0' + CAST (
      (ASCII(SUBSTRING(Column2, 9,1)) + 
      ASCII(SUBSTRING(Column2,10,1)) + 
      ASCII(SUBSTRING(Column2,11,1)) + 
      ASCII(SUBSTRING(Column2,12,1)) + 
      ASCII(SUBSTRING(Column2,13,1)))%100 
      AS NVARCHAR(2)),2) AS Column2 
     FROM Flen 
     ) 
,CullPD 
    AS (
     SELECT Column1, Column2, 
      ROW_NUMBER() OVER (PARTITION BY Column2 ORDER BY Column2) AS rowx 
     FROM TenCharPD 
     ) 

UPDATE t1 
    SET Column1 = LEFT(Column2,9) + 
    CASE rowx 
     WHEN 1 THEN RIGHT(Column2,1) 
     ELSE CHAR(rowx + CAST (RIGHT(Column2,1) AS INT) * 5 + 63) 
     END 
    FROM @Table t1 
     JOIN CullPD cpd 
      ON t1.Column1 = cpd.Column1 

SELECT * FROM @Table 
+0

有没有办法让我使用此代码来即时更新现有表格? – Peter

+0

如果您想将Column1中的值替换为Column2中的值? – DaveX

+0

是的。获取查询很好,但我也需要更新列,谢谢! – Peter