将ID列表转换为其他值

时间:2013-10-14 01:29:46

标签: sql sql-server-2005

我从查询返回一个字符串,该字符串将id列表返回给另一个表。该字符串可以包含1个id或由逗号分隔的ID列表。

我想转换id列表,以便从ids主表中引用另一个字段(在本例中为名称)。

E.g。 select * from task返回:

taskid,jobid,start,finish

1,"333",09:00,12:00

2,"334",08:00,16:00

3,"333,334",09:00,17:00

我希望引用“job”表格,以便在字符串中返回“job.name”代替job.jobid。所以它看起来像这样:

taskid,jobid,start,finish

1,"Wash",09:00,12:00

2,"Dry",08:00,16:00

3,"Wash,Dry",09:00,17:00

1 个答案:

答案 0 :(得分:0)

您遇到了存储非规范化,特别是分隔数据的众多问题之一。从关系上讲,标准解决方案是创建一个联结表来表示taskjob之间的这种多对多关系(例如“JobToTask”)。

但是,如果你无法改变目前的情况,一种方法是循环你的集合并一次迭代一次:

-- Create a temporary spot for id replacements
declare @output table (
    taskid int, jobnamelist varchar(1000)
)
insert into @output select taskid, ',' + jobid + ',' from task

-- Run replacements
while exists (select null from @output t join job j on t.jobnamelist like '%,' + cast(j.jobid as varchar(50)) + ',%') begin
    update t
    set jobnamelist = replace(
                            jobnamelist,
                            ',' + (select cast(min(jobid) as varchar(11)) from job where t.jobnamelist like '%,' + cast(jobid as varchar(50)) + ',%') + ',',
                            ',' + (select name from job where jobid = (select min(jobid) from job where t.jobnamelist like '%,' + cast(jobid as varchar(50)) + ',%')) + ','
                        )
    from @output t
    where exists (select null from job where t.jobnamelist like '%,' + cast(jobid as varchar(50)) + ',%')
end

-- Get final output
select taskid, substring(jobnamelist, 2, len(jobnamelist) - 2) as jobnamelist
from @output

--   taskid jobnamelist
--   ------ -----------
--        1 Wash
--        2 Dry
--        3 Wash,Dry

特别注意在找到或进行替换时,将分隔符添加到字符串的两端。这可以防止您更换部分ID(例如33在334中)。

如果必须在单个select语句中执行此操作,则可以使用recursive CTE运行类似的逻辑。

要考虑的一个问题是,如果job.name列中存在job.id,那么您最终会更换两次(或更多)内容并因此需要内置检查(可能是替换历史字段或临时表)。