在没有主键的表中过滤重复项

时间:2011-10-08 01:42:03

标签: sql tsql sql-server-2008

我非常感谢您对以下问题的帮助:

我有一个表(stock_header)有3列感兴趣的

catalogue_code  purcha  stock_
--------------  ------  ------
1001            Box     Box
1001            Box     Box
1002            EA      EA
1002            Set     Set
1002            Kit     Kit
1004            Set     Set

我想使用以下规则提取信息:

  • 如果catalogue_code是重复的并且其所有的purchase和stock_属性具有相同的值(例如catalogue_code 1001),请选择任何记录。
  • 如果catalogue_code是重复的,并且其某些purchase和stock_属性包含不同的值(例如catalogue_code 1002),请选择具有purcha ='EA',stock_ ='EA'的记录。

我在T-SQL中实现这个逻辑时遇到了困难。

更新:只是想提一下原始表没有主键。完成删除重复项,以便catalogue_code可以作为主键。

Update2 :不幸的是,Nick和Elian的回答并没有解决问题。这是我的潜在实现的伪代码:

  1. 查找所有重复的catalogue_codes
  2. 对于每个副本,请执行:
  3. 获取任何一对stock_和purcha属性。比较选定的对 到所有其他对并将结果存储在变量中 (numberOfIdenticalRecords)。
  4. 如果numberOfIdenticalRecords = 1(意思是 所有其他记录都有不同的库存和购买价值)。 在这种情况下,选择具有purchase ='EA'和stock_ =的记录 'EA'。
  5. 如果numberOfIdenticalRecords> 1(意思是所有的 记录包含相同的stock_和购买价值),选择任何 记录。
  6. 此实现的一个重大缺点是它是程序性的,而SQL是声明性的。即使有可能实现它,也很难理解和维护它。我是在思考整件事吗?有没有更简单的方法呢?

2 个答案:

答案 0 :(得分:2)

在标题中,您提到删除行,但您的问题听起来像是您想要一个选择查询。我必须说你的要求听起来有点奇怪,但我想以下查询会给你你想要的东西:

select 
    catalogue_code, purcha, stock_
from 
    stock_header
where 
    (purcha = 'EA' and stock_ = 'EA') 
    or catalogue_code not in(select catalogue_code from stock_header where purcha = 'EA' AND stock_ = 'EA')
group by 
    catalogue_code, purcha, stock_

如果你真的需要删除行,那么你需要一些东西来唯一地识别一行,比如他评论中提到的Erwin Brandstetter。

答案 1 :(得分:2)

declare @T table
(
  catalogue_code int,
  purcha varchar(5),
  stock_ varchar(5)
)

insert into @T values
(1001,            'Box',     'Box'),
(1001,            'Box',     'Box'),
(1002,            'AA',      'AA'),
(1002,            'MM',      'MM'),
(1002,            'EA',      'EA'),
(1002,            'Set',     'Set'),
(1002,            'Kit',     'Kit'),
(1004,            'Set',     'Set')

;with C as
(
  select *,
         row_number() over(partition by catalogue_code 
                           order by case when purcha = 'EA'
                                         then 0
                                         else 1
                                    end) as rn
  from @T
)
select *
from C
where rn = 1

结果:

catalogue_code purcha stock_ rn
-------------- ------ ------ --------------------
1001           Box    Box    1
1002           EA     EA     1
1004           Set    Set    1

在SE-Data Explorer上试用:http://data.stackexchange.com/stackoverflow/q/114648/