【问题标题】:How to make duplicate values unique?如何使重复值唯一?
【发布时间】:2014-02-27 08:48:01
【问题描述】:

我的列中有重复值的记录。

例如:

INVOICENUM  PRODUCT
-------------------
  789789    ABROPT
  789789    ABROPT
  719648    AZGTEL
  754114    GRTYPT

我有 2 条带有重复发票编号的记录,第一个编号我想添加“a”,第二个编号我想添加“b”,依此类推。

INVOICENUM  PRODUCT
-------------------
 789789a    ABROPT
 789789b    ABROPT
 719648     AZGTEL
 754114     GRTYPT

如何使用 SQL 解决此问题 - 我使用的是 SQL Server 2012 和 Microsoft SQL Server Management Studio 11.0.3000.0?

【问题讨论】:

  • 您是否尝试过任何查询?
  • 是否有可能第三次复制?
  • 您使用的是哪个 DBMS?
  • SQL Server 2012 和 Microsoft SQL Server Management Studio 11.0.3000.0
  • 您是否有任何未指定的 id 列?

标签: sql sql-server-2012 ssms


【解决方案1】:

此类问题通常通过分析函数解决。

select case
         when (count(1) over(partition by InvoiceNum) > 1) then
           InvoiceNum + Char(row_Number() over(partition by InvoiceNum order by InvoiceNum) + 96)
         else
           InvoiceNum
       end as InvoiceNum,
       Product    
  from MyTable

分析函数的主要优势性能

【讨论】:

  • 该操作在问题 cmets 中确认了 SQL Server 2012
  • 这与我的答案几乎相同(使用 ascii 代码根据行号播种字符)
  • 注意:您使用 64 来开始字符(这将给出大写字母)@jitsCode 在示例中使用了小写字母...
  • @Chris Moutray:谢谢!我错过了这个问题。我已将代码中的 64 更新为所需的 96。
  • @DmitryBychenko 我知道它现在是如何工作的(但我使用的是 sql 2008)如果我从案例条件中删除 order by 并且如果我更改 || 我可以让它工作到+。如果列已经是 varchar,也不确定是否需要转换为 varchar。
【解决方案2】:

好吧,假设 SQL Server(具有行号功能)那么这似乎工作

select
    INVOICENUM = case 
        when INVOICENUM in (select INVOICENUM from YourTable group by INVOICENUM having COUNT(*) > 1)
        then INVOICENUM + char(96+row_number() over (partition by INVOICENUM order by INVOICENUM))
        else INVOICENUM 
    end,
    PRODUCT,
    OtherColumn,
    AnotherColumn
from 
    YourTable

虽然不是特别优雅...

这里的想法是获取一个行号来播种 int-to-character 函数CHAR(...)。其中 96 是 a 之前字符的 ASCII 码 - 所以行号 1 给出 a(即 97 的 Ascii 代码),行号 2 给出 b(即 98 的 Ascii 代码)等等... 我已经在其中抛出了 case 语句以排除没有重复项的情况,因此它只是返回 InvoiceNum 而不添加字母......

这是我的测试示例...

declare @data table (INVOICENUM nvarchar(100), PRODUCT nvarchar(100))

insert into @data
values ('789789', 'ABROPT')
,('789789', 'ABROPT')
,('719648', 'AZGTEL')
,('754114', 'GRTYPT')

select
    INVOICENUM = case 
        when INVOICENUM in (select INVOICENUM from @data group by INVOICENUM having COUNT(*) > 1)
        then INVOICENUM + char(96+row_number() over (partition by INVOICENUM order by INVOICENUM))
        else INVOICENUM 
    end,
    PRODUCT
from 
    @data

【讨论】:

  • 我的表包含数千条记录和超过 20 列,我刚刚提到了 2 列和 4 条记录:p
  • @jitsCode 不确定您的意思是什么? @data 是否可以帮助测试您的情况下的问题,您将 @data 替换为您的表名,并将您想要的列添加到选择中...
  • 我必须在插入语句中写下所有记录吗?或者有其他方法可以做到这一点。
  • @jitsCode 请不要采取这种错误的方式,但我假设您知道一些 sql 并且您可以采用我的解决方案并将其应用于您的特定数据库架构(即您的表和列)。忽略测试示例,即声明和填充@data 的代码,并专注于我放置from YourTable 的第一个代码块。
  • @jitsCode 我建议您查看 Dmitry Bychenko 的答案 - 它的想法相同,但案例编码以不同的方式完成 - 它应该工作得更快。跨度>
猜你喜欢
  • 1970-01-01
  • 2017-01-13
  • 2019-06-17
  • 2013-10-12
  • 1970-01-01
  • 2021-12-23
  • 2013-07-18
  • 2013-04-10
  • 2020-02-25
相关资源
最近更新 更多