关于在T-SQL中为CASE设计更快的算法的问题,我将告诉他

时间:2009-12-02 10:07:15

标签: sql-server database algorithm tsql

这是CASE

我有一个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 在更新后,表格将如下所示。

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 个答案:

答案 0 :(得分:1)

这应该以基于集合的方式解决相对简单:

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

这将模式匹配,但排除匹配到它自己 - 它不太理想然而我猜测在这个过程之后你将删除重复或什么,因为有一个表有多个重复,没有其他区别值有点奇怪。

答案 1 :(得分:0)

(类似)这可能会有所帮助:

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))

虽然你会用那些重复的东西伤害自己......

答案 2 :(得分:0)

这是我的代码,持续约3分钟(当grup名称增加时,速度快速增加)。我不能使用它,因为我不应该在这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

答案 3 :(得分:0)

使用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. 如果组名称是稳定的,请使用短到长名称映射构建一个permenant表,而不是每次都创建一个临时表。
  2. 短名称和grup上的索引可以加快连接速度。试试看。
  3. 系统可以修改短名称吗?