изменить идентификационный номер, чтобы сгладить дубликаты в таблице - PullRequest
0 голосов
/ 08 июля 2011

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

Большинство из них являются новыми (никогда не были замечены в системе ранее), но некоторые приходят снова. Что мне нужно сделать, это добавить альфа к концу идентификационного номера, если номер найден в архиве, но только если данные в строке отличаются от данных в архиве, и это нужно делать последовательно , IE, если 12345 видят во второй раз с другими данными, я изменяю его на 12345A, и если 12345 снова видится и снова отличается, мне нужно изменить его на 12345B и т. Д.

Первоначально я попытался использовать цикл where, в котором он поместил бы все записи «увиденные снова» во временную таблицу, а затем присвоил A первый раз, затем удалил те, назначил B тому, что осталось, удалил те и т. Д. До тех пор, пока временная таблица не опустела, но это не сработало.

С другой стороны, я думал о попытке подзапросов, как в:

update table
set IDNO= (select max idno from archive) plus 1

Есть предложения?

Ответы [ 3 ]

0 голосов
/ 10 июля 2011

Что происходит, когда вы добираетесь до 12345Z?

В любом случае, слегка измените структуру таблицы, вот рецепт:

  1. Отбросьте все индексы на ID.

  2. Разделить ID (очевидно, varchar) на ID_Num (long int) и ID_Alpha (varchar, не null).Задайте значение по умолчанию для ID_Alpha пустой строки ('').
    Итак, 12345B (varchar) станет 12345 (long int) и 'B' (varchar) и т. Д.

  3. Создать уникальный, идеально кластеризованный индекс для столбцов ID_Num и ID_Alpha.
    Сделать это первичным ключом.Или, если необходимо, используйте автоинкрементное целое число в качестве псевдо-первичного ключа.

  4. Теперь, при добавлении новых данных, поиск дубликатов идентификационных номеров тривиален, и последний ID_Alpha может быть полученс простой операцией max().

  5. Устранение дублирующихся идентификаторов теперь должно быть более простой задачей с использованием либо цикла while, либо курсора (если необходимо).
    Но этоТакже должно быть возможно избежать «Строка путем агонизирующей строки» (RBAR) и использовать подход, основанный на множестве.Несколько дней чтения статей Джеффа Модена , должны дать вам идеи на этот счет.

0 голосов
/ 12 июля 2011

Вот мое окончательное решение:

update a
set IDnum=b.IDnum
from tempimiportable A inner join 
    (select * from archivetable
     where IDnum in 
     (select max(IDnum) from archivetable
      where IDnum in 
       (select IDnum from tempimporttable)
      group by left(IDnum,7) 
      )
     ) b
on b.IDnum like a.IDnum + '%'
WHERE 
*row from tempimport table = row from archive table*

, чтобы установить для входящих строк тот же IDnum, что и для старых строк, а затем

update a
set patient_account_number = case 
    when len((select max(IDnum) from archive where left(IDnum,7) = left(a.IDnum,7)))= 7 then a.IDnum + 'A'
    else left(a.IDnum,7) + char(ascii(right((select max(IDnum) from archive where left(IDnum,7) = left(a.IDnum,7)),1))+1)
    end
from tempimporttable a
where not exists ( *select rows from archive table* )

Я не знаю, хочет ли кто-либоуглубляться в это, но я ценю конструктивную критику ...

0 голосов
/ 08 июля 2011

Как насчет этого как идеи? Имейте в виду, это в основном псевдокод, так что настройте по своему усмотрению.

С "src" в качестве таблицы, в которую в конечном итоге будут вставлены все данные, и "TMP" в качестве вашей временной таблицы ... и это предполагает, что столбец идентификатора в TMP равен double .

do
    update tmp set id = id + 0.01 where id in (select id from src);
until no_rows_changed;

alter table TMP change id into id varchar(255);

update TMP set id = concat(int(id), chr((id - int(id)) * 100 + 64);

insert into SRC select * from tmp;
...