1

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

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

例如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
4

1 回答 1

0

您遇到了存储非规范化和特别是分隔数据的众多问题之一。task从关系上讲,标准的解决方案是创建一个联结表来表示和之间的这种多对多关系job(例如“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 中)。

如果您必须在单个选择语句中执行此操作,您可能会使用递归 CTE来运行类似的逻辑。

要考虑的一个极端情况是,如果您的列job.name中存在一个job.id...您最终会替换两次(或更多)的东西,因此必须对此进行检查(替换历史字段或临时表,可能)。

于 2013-10-25T22:16:41.740 回答