2010-12-30 4 views
5

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

LName, FName, Email 
----- ----- ----- 
Smith Bob [email protected] 
Smith Bob NULL 
Doe Jane NULL 
White Don [email protected] 

Я хотел бы иметь результаты запроса вернуть «дубликат» записи, которая не имеет письмо NULL, но все-таки вернуть NULL Email, когда не дублируется.

E.g.

Smith Bob [email protected] 
Doe Jane NULL 
White Don [email protected] 

Я думаю, что решение аналогично Sql, remove duplicate rows by value, но я не очень понимаю, если требования Аскер такие же, как у меня.

Любые предложения?

Благодаря

+0

Спасибо за решения от Cybernate и Michael Goldshteyn. Пошел с FooLman b/c, это было первое решение, которое выполнило эту работу. Интересно видеть различные методы разрешения. – jimueller

ответ

7

Это падает нулевые строки, если есть какие-либо значения не являющиеся нулевыми.

SELECT lname 
     , fname 
     , MIN(email) 
FROM YourTable 
GROUP BY 
     lname 
     , fname 

тестовый скрипт

DECLARE @Test TABLE (
    LName VARCHAR(32) 
    , FName VARCHAR(32) 
    , Email VARCHAR(32) 
) 

INSERT INTO @Test 
    SELECT 'Smith', 'Bob', '[email protected]' 
    UNION ALL SELECT 'Smith', 'Bob', 'NULL' 
    UNION ALL SELECT 'Doe', 'Jane', 'NULL' 
    UNION ALL SELECT 'White', 'Don', '[email protected]' 

SELECT lname 
     , fname 
     , MIN(Email)   
FROM @Test 
GROUP BY 
     lname 
     , fname 
+1

+1 Это, безусловно, самое легкое решение *, которое делает то, что задано. Сообщество, похоже, страдает от переоценки . –

+0

@ Lieven - Это не сработает! Где есть какая-либо логика для сохранения нулевых строк, если нет никаких ненулевых? –

+0

@Martin, запрос производит вывод, запрошенный op для заданных входов, не так ли (или я снова сработал)? –

3

Вот относительно простой запрос, который использует стандартный SQL и делает только это:

SELECT * FROM Person P 
WHERE Email IS NOT NULL OR -- Take all people with non-null e-mails 
     Email IS NULL AND -- and all people with null e-mails, as long as 
     NOT EXISTS   -- there is no duplicate record of the same person 
      (SELECT *  -- with a non-null e-mail 
      FROM Person P2 
      WHERE P2.LName=P.LName AND P2.FName=P.FName AND P2.Email IS NOT NULL) 
+0

Вы подразумеваете, что 'row_number' не является стандартным SQL? –

+0

Я не подразумеваю ничего - просто предлагаю простое решение, использующее не что иное, как стандартный SQL-запрос, включающий подвыбор. Но если вам нужен ответ на ваш вопрос относительно ROW_NUMBER, нет, это не стандартный SQL, и ни один из них не является PARTITION BY. –

+0

ANSI SQL 1999 [в соответствии с здесь] (http://ss64.com/ora/syntax-analytic.html) Не так, чтобы стандартный SQL всегда указывался OP в любом случае. –

7

Вы можете использовать row_number() аналитическую функцию:

SELECT * 
    FROM (
       SELECT a.*, ROW_NUMBER() OVER(PARTITION BY LName, FName ORDER BY Email DESC) rnk 
        FROM <YOUR_TABLE> a 
       ) a 
WHERE RNK = 1 
+0

+1 Это, вероятно, будет более эффективным, чем самоподключение. Этот метод можно использовать для удаления, а также для моего ответа. –

1

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

+0

Я согласен и понимаю, но не так много могу сделать с этим в сфере ИТ-бизнеса. Это реальность данных, с которыми я должен работать. – jimueller

+0

@ jrm82, тем более важно фиксировать такие вещи в корпоративных приложениях! Просто потому, что это апин, это не значит, что вы не должны этого делать. Это не вызовет никаких проблем навсегда, если вы не исправите. – HLGEM

+0

HLGEM - Я не «владею» данными, и у меня нет возможности работать над тем, что я хочу. – jimueller