Как я могу написать запрос, чтобы показать сведения о клиентах с повторяющимися именами?

#sql #oracle

#sql #Oracle

Вопрос:

Я довольно долго искал и, похоже, не могу найти решение, которое соответствует тому, что мне нужно.

У меня есть таблица со многими, многими клиентами, и проблема в том, что в этой таблице много, много дубликатов.

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

Я использовал этот код:

 SELECT COUNT(NAME), NAME
  FROM DEV.ALL_CUSTOMER
  GROUP BY NAME
  HAVING COUNT(NAME) > 1;
  

Что дает результаты, которые отображаются следующим образом:

 COUNT(NAME) |       NAME
------------|-------------------
     3      | Smith, John
     2      | Doe, Jane
     2      | Doe, Joe
     2      | Smith, Jane
  

Затем я добавил все необходимые мне информационные поля:

 SELECT COUNT(NAME), NAME, TOTAL_PURCHASED, ADDRESS, CITY, STATE_PROV, POSTAL_CODE, COUNTRY, HOME_PHONE, WORK_PHONE, WORK_EXT, OTHER_PHONE, EMAIL_ADDRESS
  FROM DEV.ALL_CUSTOMER
  GROUP BY NAME, TOTAL_PURCHASED, ADDRESS, CITY, STATE_PROV, POSTAL_CODE, COUNTRY, HOME_PHONE, WORK_PHONE, WORK_EXT, OTHER_PHONE, EMAIL_ADDRESS
  HAVING COUNT(NAME) > 1;
  

Но при этом они по-прежнему группируются и не отображают информацию для каждой записи:

 COUNT(NAME) |    NAME     | TOTAL_PURCHASED | ADDRESS |  CITY ...
------------|-------------|-----------------|---------|------- ..
     3      | Smith, John |        0        | (null)  | (null) ..
     2      | Doe, Jane   |        0        | (null)  | (null) ..
     2      | Doe, Joe    |        0        | (null)  | (null) ..
  

Но я точно знаю, что один из пяти клиентов «John Smith» купил что-то.

Вместо этого я хотел бы, чтобы результаты выглядели так:

 NAME        | TOTAL_PURCHASED | ADDRESS       |  CITY ...
------------|-----------------|---------------|------- ..
Smith, John |       250       | 123 Fake St.  | (null) ..
Smith, John |        0        | (null)        | Oshawa ..
Smith, John |       300       | (null)        | Toronto .
Doe, Jane   |        0        | (null)        | (null) ..
Doe, Jane   |       300       | 456 Fake St.  | Toronto .
Doe, Joe    |      11235      | (null)        | (null) ..
Doe, Joe    |        0        | (null)        | (null) ..
  

Комментарии:

1. Возможно, я что-то упускаю, но разве ваши желаемые результаты не просто «выбрать * из порядка all_customers по имени»? Возможно, с where name in (<<your group by/ having>>) помощью .

2. Я пробовал SELECT [FIELDS] FROM DEV.ALL_CUSTOMER HAVING COUNT(NAME) > 1; , но это ошибки.

Ответ №1:

Используйте оконные функции:

 SELECT c.*
FROM (SELECT c.*, COUNT(*) OVER (PARTITION BY NAME) as cnt
      FROM DEV.ALL_CUSTOMER c
     ) c
WHERE cnt > 1
ORDER BY NAME;
  

Это даст вам строки, которые дублируются NAME .

Комментарии:

1. Мне нужны только те поля, которые я опубликовал во втором SELECT заявлении. Должен ли я просто заменить c.* оба выбранных в вашем коде этими конкретными полями? Вот так: SELECT [SPECIFIC FIELDS] FROM (SELECT [SPECIFIC FIELDS], COUNT(NAME) OVER (PARTITION BY NAME) as cnt FROM DEV.ALL_CUSTOMER c ) c WHERE cnt > 1 ORDER BY NAME;

2. @WolfieeifloW . , , Вы можете просто поместить нужные вам поля во внешний select .