避免在结果表中重复

时间:2013-12-06 14:46:35

标签: sql tsql match

目前我的TSQL查询中有这个表(#tmp):

| a  |  b |
|:---|---:|
| 1  | 2  |
| 1  | 3  |
| 4  | 5  |
| 6  | 7  |
| 9  | 7  |
| 4  | 0  | 

此表包含我要从另一个表中删除的行的ID。问题是,我不能将相同的'a'与多个'b'匹配,反之亦然,单个'b'不能与多个'a'匹配。所以基本上我需要删除(1,3),(9,7)和(4,0),因为它们的'a'或'b'已被使用。我正在使用下面的代码来尝试这样做,但似乎给定的'a'有多个对应的'b'高于'且'低于'a'会导致问题。

IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
  DROP TABLE #tmp

IF OBJECT_ID('tempdb..#KeysToDelete') IS NOT NULL
  DROP TABLE #KeysToDelete

CREATE TABLE #tmp (a int, b int)

INSERT INTO #tmp (a, b)
VALUES (1,2), (1,3),(4,5),(6,7), (9,7), (4,0)

SELECT * FROM #tmp

-- Get the minimum b for each a
select distinct
  a,
  (SELECT MIN(b) FROM #tmp t2 WHERE t2.a = t1.a) AS b
INTO #KeysToDelete
FROM #tmp t1
WHERE t1.a < t1.b

-- Get the minimum a for each b
INSERT INTO #KeysToDelete
select distinct
  (SELECT MIN(a) FROM #tmp t2 WHERE t2.a = t1.a) AS a,
  b
FROM #tmp t1
WHERE t1.a > t1.b

SELECT DISTINCT a, b 
FROM #KeysToDelete
ORDER BY 1, 2

输出是这样的:

| a  |  b |
|:---|---:|
| 1  | 2  |
| 4  | 0  |
| 6  | 7  |
| 9  | 7  |

但我真的想要这个:

| a  |  b |
|:---|---:|
| 1  | 2  |  -- it would match requirements if this were (1,3) instead
| 4  | 5  |  -- it would match requirements if this were (4,0) instead
| 6  | 7  |  -- it would match requirements if this were (9,7) instead

如果有人知道我怎么能解决这个问题,我将不胜感激!我知道这是一个长期涉及的问题,但你可能有任何建议会很棒!

谢谢!

3 个答案:

答案 0 :(得分:2)

您的问题陈述没有明确定义。您可以通过多种方式从@tmp中删除行,从而强制执行A​​列和B列的唯一性。

这是一种方法,即使A唯一,然后使B唯一:

with todelete as (
      select t.*, row_number() over (partition by a order by newid()) as a_seqnum
      from #tmp t
     )
delete from todelete
    where a_seqnum > 1;

with todelete as (
      select t.*, row_number() over (partition by b order by newid()) as b_seqnum
      from #tmp t
     )
delete from todelete
    where b_seqnum > 1;

答案 1 :(得分:1)

试试这个:

Select * from #tmp t
Where Not exists(select * from #tmp 
                 where b = t.b 
                    and a < t.a)
  and Not exists(select * from #tmp 
                 where a = t.a 
                    and b < t.b)

答案 2 :(得分:0)

我认为我更喜欢 Gordon的解决方案 我做了类似的事情,但没有删除部分:

;WITH CTE1 ( a , b )
AS
(
select a , b from
    ( SELECT ROW_NUMBER() OVER(PARTITION BY a ORDER BY a ) AS Row , a , b
      from #tmp ) t
      where [row] = 1 
),
CTE2 (a, b)
AS
(
select a , b from
    ( SELECT ROW_NUMBER() OVER(PARTITION BY b ORDER BY a ) AS Row , a , b
      from #tmp ) t
      where [row] = 1 
)

select * from CTE2