目前我的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
如果有人知道我怎么能解决这个问题,我将不胜感激!我知道这是一个长期涉及的问题,但你可能有任何建议会很棒!
谢谢!
答案 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