【问题标题】:T-SQL Truncate text and add number at the end to avoid duplicatesT-SQL 截断文本并在末尾添加数字以避免重复
【发布时间】:2016-07-26 15:48:50
【问题描述】:

我需要将一列中的数据截断为 10 个字符。但是,我不能有任何重复项,所以我希望任何重复项以 ~1 结尾,第二次重复以 ~2 结尾。这是我所拥有的示例:

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

【问题讨论】:

  • 如果您截断“The ABC Company Inc.”和“The ABC Cooperative”到 10 个字符,您将留下两个“The ABC Co”,导致重复。
  • ABC ~1 IS 10 个字符
  • 如果有 10 个或更多重复项怎么办?
  • 老实说,如果有 10 个或更多,我会去删除重复项...大声笑...就我而言,我遇到的最多是 5 个重复项。

标签: sql sql-server sql-server-2008 tsql sql-server-2012


【解决方案1】:

首先,您关心的是前 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

【讨论】:

  • 值得注意的是,编号不能保证是稳定的,如果添加或删除行,编号很可能会发生变化。这并没有错,但它可能会在以后的某个时候让 OP 感到惊讶。
  • 这看起来像我需要的。我正在尝试修改查询,但第一行with toupdate as 遇到问题。我是否应该在此代码中添加任何其他内容?我用我想更新的表替换了toupdate。 SQL Management Studio 说“from t”附近有语法错误,不知道如何解决...
  • @彼得。 . .该表位于fromt 之间的from 子句中。
  • 谢谢!我在case 语句中添加了end,为表添加了一个ColumnID,这样我就可以加入它来进行更新。谢谢!
【解决方案2】:
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

【讨论】:

  • 正如 Gordon 提到的,10 可能是 8
【解决方案3】:

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

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

【讨论】:

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

假设您的表是 COMPANY,字段是 CompanyName..... 您将不得不 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

【讨论】:

    【解决方案5】:
    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
    

    【讨论】:

    • 有没有办法让我使用此代码即时更新我现有的表?
    • As-in,您想将 Column1 中的值替换为 Column2 中的值吗?
    • 请。获取查询很好,但我还需要一些东西来更新列,谢谢!
    • 好的,你去。如果由于加入更新而有两个相同的公司名称,它将不起作用。如果您的原始表也有唯一的行标识符,那么创建它就很容易了。如果你需要我可以给你看。我使用“Acme”来表明它在公司名称较短时有效;和 'T​​en Char 123' 和 'Ten Char 456' 来展示当第一部分相似时它是如何工作的。我应该做'Ten Char 123'和'Ten Char 132',所以你可以看到它是'Ten Char14'和'Ten Char1b'。我要去编辑它。
    • 发现了另一个当存在“十字符 123”和“十字符 124”时无法区分“十字符 132”和“十字符 142”的错误。刚刚将“ELSE CHAR(rowx+95)”替换为“ELSE CHAR(rowx + CAST (RIGHT(Column2,1) AS INT) * 5 + 85)”。显然有一些限制,但这应该会减少它们。
    猜你喜欢
    • 2016-05-27
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2016-08-14
    • 2013-03-20
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    相关资源
    最近更新 更多