【问题标题】:Convert list of IDs into other values将 ID 列表转换为其他值
【发布时间】:2013-10-14 01:29:46
【问题描述】:

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

我想转换 id 列表,以便引用 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

【问题讨论】:

  • 你需要一个INNER JOIN
  • 但是我怎样才能让字符串保持为逗号分隔值,只显示名称而不是 id?
  • 我没有注意到它是一个字符串。
  • 如果您想要一个纯 SQL 解决方案,这将很困难,因为它不能很好地处理逗号列表。通常这将通过一个连接表来完成,在 Task 和 Job 记录之间创建一个一对多的连接。

标签: sql sql-server-2005


【解决方案1】:

您遇到了存储非规范化,特别是分隔数据的众多问题之一。从关系上讲,标准解决方案是创建一个联结表来表示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.id 列中存在job.name...您最终会替换某些东西两次(或更多),因此必须为此进行检查(可能是替换历史字段或临时表)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-03
    • 1970-01-01
    • 1970-01-01
    • 2015-03-16
    • 1970-01-01
    • 2021-10-02
    • 2018-11-23
    • 1970-01-01
    相关资源
    最近更新 更多