SQL - ВЫБРАТЬ дубликаты между идентификаторами, но не показывать записи, если дубликаты встречаются для одного и того же идентификатора - PullRequest
2 голосов
/ 07 октября 2019

В настоящий момент у меня есть следующая таблица (упрощенная из реальной таблицы):

+----+-------+-------+
| ID | Name  | Phone |
+----+-------+-------+
|  1 | Tom   |   123 |
|  1 | Tom   |   123 |
|  1 | Tom   |   123 |
|  2 | Mark  |   321 |
|  2 | Mark  |   321 |
|  3 | Kate  |   321 |
+----+-------+-------+

Мой желаемый вывод в операторе SELECT:

+----+------+-------+
| ID | Name | Phone |
+----+------+-------+
|  2 | Mark |   321 |
|  3 | Kate |   321 |
+----+------+-------+

Я хочу выбратьдублирует только тогда, когда они встречаются между двумя различными идентификаторами (например, Марк и Кейт используют один и тот же номер телефона), но не для отображения записей для идентификаторов, которые используют один и тот же номер телефона только для себя (например, Том).

Может кто-нибудь посоветовать, как этого можно достичь?

Ответы [ 3 ]

1 голос
/ 07 октября 2019

Вы можете использовать условие EXISTS с коррелированным подзапросом, чтобы убедиться, что существует другая запись с таким же phone и другим id. Нам также нужно DISTINCT, чтобы удалить дубликаты в наборе результатов.

SELECT DISTINCT id, name, phone
FROM mytable t
WHERE EXISTS (
    SELECT 1
    FROM mytable t1
    WHERE t1.phone = t.phone AND t1.id <> t.id
)

Демонстрация на DB Fiddle :

| id  | name | phone |
| --- | ---- | ----- |
| 2   | Mark | 321   |
| 3   | Kate | 321   |
0 голосов
/ 07 октября 2019

Можно использовать несколько связанных запросов с группировкой, имеющей, как показано ниже

   Select ID, NAME, max(PHONE) From
 (Select * From Table) t group by id, 
          name having
    1= max( 
    case
   When phone in (select phone from 
     table where t.id<>Id) then 1 else 0) 
      end)

enter image description here

0 голосов
/ 07 октября 2019

Для этого вы можете использовать оконные функции:

select t.*
from (select t.*,
             row_number() over (partition by phone, name order by id) as seqnum,
             min(id) over (partition by phone) as min_id,
             max(id) over (partition by phone) as max_id
      from t
     ) t
where seqnum = 1 and min_id <> max_id;

Другой метод использует агрегацию и оконную функцию:

select phone, name, id
from (select phone, name, id,
             count(*) over (partition by phone) as num_ids
      from t
      group by phone, name, id
     ) pn
where num_ids > 1;

Оба имеют преимущество перед существующим решением (GMB's) что они ссылаются на «таблицу» только один раз. Это может быть большим преимуществом, если таблица представляет собой сложное представление или запрос. Если производительность является проблемой, я бы посоветовал вам протестировать несколько вариантов, чтобы увидеть, какой из них лучше всего работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...