2013-12-06 2 views
0

В настоящее время у меня есть эта таблица (#tmp) в моем TSQL запроса:Избежание дубликатов в моей таблице результатов

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

Эта таблица содержит идентификаторы строк, которые я хочу, чтобы удалить из другой таблицы. Дело в том, что я не могу иметь одинаковое совпадение с несколькими «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 

Если у кого есть какие-либо идеи, как я мог бы быть в состоянии исправить это было бы весьма признателен ! Я знаю, что это длинные вопросы, но любые предложения, которые у вас могут быть, были бы замечательными!

Спасибо!

ответ

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) 
+0

Это похоже на работу! Спасибо! – intA

2

Ваше заявление о проблеме не определено. Есть несколько способов, которые вы можете удалить строки из @tmp, исполнивших уникальности столбцов A и B.

Вот один подход, который должен сделать уникальное, а затем сделать 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; 
+0

Это работает! Я не знаком с множеством функций, которые вы использовали, но я думаю, что могу пойти с решением, представленным Чарльзом ниже, потому что это похоже на работу, и это кажется немного более простым. – intA

0

я думаю, что мне нравится решение в Гордона лучше я сделал нечто подобное, но без удаления частей:

;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 
Смежные вопросы