Вопрос об определении более быстрого алгоритма в T-SQL для CASE, о котором я буду рассказывать - PullRequest
0 голосов
/ 02 декабря 2009

Вот дело

У меня есть таблица sql, состоящая только из одного столбца данных, состоящего из нескольких имен групп. Вот как выглядит таблица:

OPEN SYSTEMS SUB GR 
OPEN SYSTEMS SUB GR (GM/BTIB(1111)/BTITDBL(2222)/BTVY(4444)/ACSVTYSAG
INFRASTRUCTURE SOFT SUB GR 
INFRASTRUCTURE SOFT SUB GR (GM/BTIB(1111)/BTUGBL(3333)/BTUGBL(3333)/BTAUSGAG
MAIN SERVER ONLİNE SYS SUB GR (GM_BTIB(1111)_BTITDBL(2222)_BTSY(5555)_ANBOSAG
MAIN SERVER SUB GR 
MAIN SERVER SUB GR (GM_BTIB(1111)_BTITDBL(2222)_BTVY(4444)_ANBVTYSAG
XTM/YTM SUB GR 
XTM/YTM SUB GR (GM_BTIB(1111)_BTUGBL(3333)_BTAU(6666)_BTABAG
CARDS SUB GR (GM_BTIB(1111)_BTUGBL(3333)_BTKOU(7777)_BTBKAG
SYSTEMS DEV. SUB GR (GM_BTIB(1111)_BTSGBL(8888)_BTPB(9999)_BBASGAG
PERSONAL B. SUB GR 
PERSONAL B. SUB GR (GM/BTIB(1111)/BTUGBL(3333)/BTAU(6666)/BTBISAG

И так продолжается. Как видите, некоторые из групп имеют повторяющиеся имена, такие как

PERSONAL B. SUB GR 
PERSONAL B. SUB GR (GM/BTIB(1111)/BTUGBL(3333)/BTAU(6666)/BTBISAG

Что я хочу сделать, так это то, что я хочу обновить "короткие версии имен групп" на "более длинные версии их". В качестве примера PERSONAL B. SUB GR будет заменен на PERSONAL B. SUB GR (GM / BTIB (1111) / BTUGBL (3333) / BTAU (6666) / BTBISAG Like после обновления таблица будет выглядеть следующим образом.

OPEN SYSTEMS SUB GR (GM/BTIB(1111)/BTITDBL(2222)/BTVY(4444)/ACSVTYSAG
OPEN SYSTEMS SUB GR (GM/BTIB(1111)/BTITDBL(2222)/BTVY(4444)/ACSVTYSAG
INFRASTRUCTURE SOFT SUB GR (GM/BTIB(1111)/BTUGBL(3333)/BTUGBL(3333)/BTAUSGAG
INFRASTRUCTURE SOFT SUB GR (GM/BTIB(1111)/BTUGBL(3333)/BTUGBL(3333)/BTAUSGAG
MAIN SERVER ONLİNE SYS SUB GR (GM_BTIB(1111)_BTITDBL(2222)_BTSY(5555)_ANBOSAG
MAIN SERVER SUB GR (GM_BTIB(1111)_BTITDBL(2222)_BTVY(4444)_ANBVTYSAG
MAIN SERVER SUB GR (GM_BTIB(1111)_BTITDBL(2222)_BTVY(4444)_ANBVTYSAG
XTM/YTM SUB GR (GM_BTIB(1111)_BTUGBL(3333)_BTAU(6666)_BTABAG
XTM/YTM SUB GR (GM_BTIB(1111)_BTUGBL(3333)_BTAU(6666)_BTABAG
CARDS SUB GR (GM_BTIB(1111)_BTUGBL(3333)_BTKOU(7777)_BTBKAG
SYSTEMS DEV. SUB GR (GM_BTIB(1111)_BTSGBL(8888)_BTPB(9999)_BBASGAG
PERSONAL B. SUB GR (GM/BTIB(1111)/BTUGBL(3333)/BTAU(6666)/BTBISAG
PERSONAL B. SUB GR (GM/BTIB(1111)/BTUGBL(3333)/BTAU(6666)/BTBISAG

Моя таблица состоит из 9000 записей, и у меня есть алгоритм, который делает это, хотя он работает медленно, около 3 минут, чтобы завершить запрос, однако я собираюсь сделать что-то простое. Мне нужен более быстрый алгоритм.

Спасибо за помощь.

Ответы [ 4 ]

1 голос
/ 02 декабря 2009

Это должно быть относительно просто решить на основе набора:

UPDATE a
SET  a.yourfield = b.yourfield 
FROM yourtable a 
INNER JOIN yourtable b on b.yourfield LIKE a.yourfield + '%' AND b.yourfield <> a.yourfield

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

0 голосов
/ 05 декабря 2009

Использование SQL Server 2000.

Данные испытаний:

create table #t (grup varchar(200))

insert into #t values ('OPEN SYSTEMS SUB GR')
insert into #t values ('OPEN SYSTEMS SUB GR (GM/BTIB(1111)/BTITDBL(2222)/BTVY(4444)/ACSVTYSAG')
insert into #t values ('INFRASTRUCTURE SOFT SUB GR')
insert into #t values ('INFRASTRUCTURE SOFT SUB GR (GM/BTIB(1111)/BTUGBL(3333)/BTUGBL(3333)/BTAUSGAG')
insert into #t values ('MAIN SERVER ONLİNE SYS SUB GR (GM_BTIB(1111)_BTITDBL(2222)_BTSY(5555)_ANBOSAG')
insert into #t values ('MAIN SERVER SUB GR')
insert into #t values ('MAIN SERVER SUB GR (GM_BTIB(1111)_BTITDBL(2222)_BTVY(4444)_ANBVTYSAG')
insert into #t values ('XTM/YTM SUB GR')
insert into #t values ('XTM/YTM SUB GR (GM_BTIB(1111)_BTUGBL(3333)_BTAU(6666)_BTABAG')
insert into #t values ('CARDS SUB GR (GM_BTIB(1111)_BTUGBL(3333)_BTKOU(7777)_BTBKAG')
insert into #t values ('SYSTEMS DEV. SUB GR (GM_BTIB(1111)_BTSGBL(8888)_BTPB(9999)_BBASGAG')
insert into #t values ('PERSONAL B. SUB GR')
insert into #t values ('PERSONAL B. SUB GR (GM/BTIB(1111)/BTUGBL(3333)/BTAU(6666)/BTBISAG')

insert into #t
select L.*
from #t L
cross join #t R

insert into #t
select L.*
from #t L
cross join #t R

Предоставление vver 33 000 тестовых рядов.

Шаг 1, создайте временную таблицу для хранения преобразования коротких имен групп в длинные имена групп:

select substring(grup, 1, charindex(' (', grup)) as short_grup
    , grup as long_grup
into #Lookup
from #t
WHERE GRUP LIKE '%(%(%)%(%)%(%)%'
group by grup

Шаг 2, используйте приведенную выше временную таблицу в операторе обновления:

update target
    set target.grup = source.long_grup
from #t target
inner join #Lookup source
on target.grup = source.short_grup

ПРИМЕЧАНИЕ: Я пытался использовать встроенный просмотр за один шаг, но это занимает гораздо больше времени (в настоящее время на 7+ минут):

update target
    set target.grup = source.long_grup
from #t target
inner join (select substring(grup, 1, charindex(' (', grup)) as short_grup
        , grup as long_grup
    from #t
    WHERE GRUP LIKE '%(%(%)%(%)%(%)%'
    group by grup) source
on target.grup = source.short_grup

Другие мысли о

  1. Если имена групп стабильны, создайте постоянную таблицу с сопоставлением коротких и длинных имен вместо создания временной таблицы каждый раз.
  2. Индексы короткого имени и группы могут ускорить объединение. Тест, чтобы увидеть.
  3. Можно ли исправить систему ввода коротких имен?
0 голосов
/ 02 декабря 2009

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

UPDATE MYTABLE
SET GRUP=ISNULL(C.BGrup,MYTABLE.Grup)

FROM 
MYTABLE
FULL OUTER JOIN
(
SELECT
AGRUP, BGRUP
FROM
(
    SELECT 
    DISTINCT GRUP AS AGRUP
    FROM 
    MYTABLE
    WHERE GRUP NOT LIKE '%(%(%)%(%)%(%)%'
) A
LEFT JOIN
(
    SELECT 
    DISTINCT 
    REPLACE(GRUP,'_','/') AS BGRUP
    FROM 
    MYTABLE
    WHERE GRUP LIKE '%(%(%)%(%)%(%)%'
) B
ON 

AGRUP = SUBSTRING(BGRUP,0,LEN(AGRUP)+2)

WHERE 
AGRUP <> '' AND 
BGRUP <> '' AND
) C
ON MYTABLE.Grup=C.AGrup
0 голосов
/ 02 декабря 2009

(что-то вроде) это может помочь:

UPDATE grp SET
  name = l.name
FROM grp s, grp l
WHERE LEN(s.name) < LEN(l.name)
  AND s.name = LEFT(l.name, LEN(s.name))

хотя ты собираешься навредить себе этими дубликатами ...

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