2014-10-19 4 views
0

У меня есть таблица оракул как этотSQL, как устранены повторяющиеся данные по столбцам

customer1 customer2 city 
A    B   NY 
B    A   NY 
A    C   NY 
A    D   NY 
D    A   NY 
C    A   NY 

Я просто заинтересован в уникальной комбинации.

A B или B A и т.д.

Выход мне нужно

customer1 customer2 city 
A    B   NY 
A    C   NY 
A    D   NY 
+0

Если ключевые столбцы сопоставимы, и если их число невелико, вы можете создать составной столбец их отсортированных-конкатенированных значений и выбрать отличительные знаки в этой временной таблице. Если вы используете этот подход, обязательно используйте что-то необычное, чтобы приклеить ключи в составном. – Dinesh

ответ

1

Я не знаю, как перевести это в Oracle (если это вообще возможно), но Postgres дает короткий, если возможно, неэффективна,

SELECT DISTINCT ON (LEAST(c1, c2), GREATEST(c1, c2)) 
    LEAST(c1, c2), GREATEST(c1, c2), city FROM t; 
1

Я думаю, что это будет делать то, что вам нужно. Операторы из двух случаев сортируют два столбца. После сортировки вы можете просто получить отдельные строки.

SELECT DISTINCT 
CASE WHEN customer1 < customer2 THEN customer1 ELSE customer2 END customer1, 
CASE WHEN customer1 > customer2 THEN customer1 ELSE customer2 END customer2, 
city 
FROM TABLE 
+0

Это должно быть более эффективным, чем мое, хотя вы теряете, кто изначально был пользователем 1/2 – Matthew

1

Мы можем получить половину пути там, требуя customer1 < = customer2, но это слишком ограничительный характер. Нам нужно добавить обратно в случаях, когда custerm1> customer2, но не в первом наборе. Оператор NOT IN будет работать для нас здесь, если мы подберем имена столбцов.

SELECT c1, c2, city 
    FROM t 
    HAVING c1 <= c2 
UNION 
    SELECT c1, c2, city 
    FROM t 
    WHERE c1 > c2 
    AND (c1, c2, city) NOT IN 
    (
    SELECT c2 AS c1 
     , c1 AS c2 
     , city 
    FROM t 
    WHERE c1 <= c2 
) 

в действии здесь: http://sqlfiddle.com/#!2/78d1c/23

1

В Oracle вы можете сделать это:

SELECT DISTINCT LEAST(customer1, customer2), 
       GREATEST(customer1, customer2), 
       city 
FROM T 

См. http://sqlfiddle.com/#!4/b73ba/1
Простой и понятный. Но не очень эффективны (не можете использовать ваш индекс).


Если вам нужно сохранить customer1 и customer2 в том же порядке, как и в исходной таблице для не-дубликатов, вам, вероятно, нужно что-то более сложное:

SELECT T.* FROM T 
JOIN (SELECT MIN(ROWID) RID 
     FROM T GROUP BY LEAST(customer1, customer2), 
       GREATEST(customer1, customer2), 
       city) V 
ON T.ROWID = V.RID 

Or (возможно лучше):

SELECT T1.* FROM T T1 
LEFT JOIN T T2 
ON T1.city = T2.city 
AND T1.customer1 = T2.customer2 
AND T1.customer2 = T2.customer1 
WHERE T2.city IS NULL OR T1.customer1 < T1.customer2 

См. http://sqlfiddle.com/#!4/f7bbd/3 для сравнения этих трех решений.

Смежные вопросы