Поиск дублирующих и отсутствующих (нулевых) значений в таблице Oracle - PullRequest
0 голосов
/ 27 июня 2018

Я ищу ошибки в таблице и хочу сообщить как дубликаты, так и пропущенные значения. Я не уверен в лучшем способе сделать это и ищу совет относительно лучшего способа достигнуть этого. Это в Oracle 12c.

Похоже, что для достижения желаемого результата:

SELECT a.id, 
       a.mainfield, 
       a.location, 
       b.counter 
FROM   maintable a 
       INNER JOIN (
                    SELECT mainfield, 
                            Count(*) counter 
                    FROM   maintable 
                    GROUP  BY mainfield 
                    HAVING Count(mainfield) > 1 OR mainfield IS NULL
                  ) b ON a.mainfield = b.mainfield OR
                  ( a.mainfield IS NULL AND b.mainfield IS NULL ) 
ORDER  BY a.mainfield; 

Это работает и дает мне идентификатор, потенциально нулевое значение MAINFIELD, местоположение и количество либо дублированных значений MAINFIELD, либо нулевых значений MAINFIELD.

Есть ли что-то более простое или потенциально более эффективное, что я мог бы использовать? Я должен признать, что мои навыки SQL довольно ржавые.

Пример данных может помочь, а может и не помочь, но идентификатор является первичным ключом, является числом и не имеет значения NULL. Другие поля являются как NVARCHAR2, так и обнуляемыми. Ни один из них не проиндексирован. Вот как может выглядеть результат. Некоторые записи являются прямыми ошибками. Некоторые очевидные опечатки. Некоторые, похоже, являются тестовыми данными.

ID      MAINFIELD   LOCATION                            COUNTER
------- ---------   ---------------------------------   -------
16626   206000650   9A OLIVER ST CENTRAL STATION        2
18805   206000650   3 SWIFT CT CENTRAL STATION          2
22409   940000170   2 MARKET ST NEWARK DE               2
22003   940000170   1 MARKET ST NEWARK NJ               2
29533   970000030   95 MILL RD ANDOVER                  2
20256   970000030   12 RAILROAD AVE                     2
29018   978900050   44 BROAD STREET                     2
28432   978900050   WASHINGTON ST AND HAMILTON AVE      2
21831   980700050   BROADWAY NEWTOWN                    2
24147   980700050   MAIN STREET LEVITTOWN               2
26418                                                   3
26738               TEST DATA                           3
26755                                                   3

Последние три строки имеют нулевое значение MAINFIELD, и таких записей три (две из которых также имеют нулевое местоположение).

После некоторого понимания приведенных выше данных я понял, что мог бы рассмотреть возможность использования NVL для устранения части условий, например так (при условии, что выбранное мной значение не будет действительным значением в основном поле):

SELECT a.id, 
       a.mainfield, 
       a.location, 
       b.counter 
FROM   maintable a 
       INNER JOIN (
                    SELECT mainfield, 
                            Count(*) counter 
                    FROM   maintable 
                    GROUP  BY mainfield 
                    HAVING Count(mainfield) > 1 OR mainfield IS NULL
                  ) b ON NVL(a.mainfield,'***NULL***') = NVL(b.mainfield.'***NULL***') 
ORDER  BY a.mainfield; 

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

Одна альтернатива, от которой я отказался, которая могла бы подойти для немного другого сценария (но был для меня худшим исполнителем), это:

SELECT  id, 
        mainfield, 
        location,
        COUNT (id) OVER (PARTITION BY mainfield) counter
FROM    maintable a
WHERE   mainfield IS NULL
OR      EXISTS(SELECT 1 from maintable b
            WHERE mainfield = a.mainfield AND ROWID <> a.ROWID)
ORDER BY a.mainfield;

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

Если что-то из вышеперечисленного дает кому-то идею лучшей альтернативы, я весь в ушах. (Например, есть ли способ указать счетчик [COUNT (id) для основного поля PARTITION BY] в предложении WHERE?)

Еще раз спасибо.

1 Ответ

0 голосов
/ 29 июня 2018

Это хороший компромисс между удобочитаемостью, надежностью и эффективностью, который был предложен Balazs Papp на плате dba.stackexchange.com: https://dba.stackexchange.com/a/210998/154392

SELECT * FROM (
SELECT  id, 
        mainfield, 
        location,
        COUNT (id) OVER (PARTITION BY mainfield) counter
FROM    maintable a
) where counter > 1 or mainfield IS NULL
ORDER BY mainfield;

Это упрощение последней альтернативы исходного поста. Он не выглядит более неэффективным, чем моя первоначальная альтернатива (насколько я могу судить), но для меня это более читабельно.

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