将一个分隔的 id 字段转换为它们的漂亮值 - 嵌套替换是最佳选择吗?
Posted
技术标签:
【中文标题】将一个分隔的 id 字段转换为它们的漂亮值 - 嵌套替换是最佳选择吗?【英文标题】:Turn a delimited field of ids into their pretty values - Are nested replaces the best option? 【发布时间】:2021-03-25 13:50:20 【问题描述】:考虑以下两个表
客户
ID | CLIENT_NAME |
---|---|
1 | Adam |
2 | Steve |
3 | Jack |
4 | Harvey |
产品
NAME | CLIENTS |
---|---|
A | 1,2,3,4 |
B | 1,3,4 |
C | 2 |
D | 1,3 |
如何进行查询,将 Products.Clients 字段替换为 Clients.Client_Name 的分隔字符串而不是 Clients.ID?
所需的查询结果
NAME | CLIENTS |
---|---|
A | Adam,Steve,Jack,Harvey |
B | Adam,Jack,Harvey |
C | Steve |
D | Adam,Jack |
以下使用嵌套替换的方法有效,但对我来说这不是“正确”的方法,特别是因为在我的情况下,每行可能有超过 4 个值 - 有什么更好的方法吗?
SELECT NAME, REPLACE(REPLACE(REPLACE(REPLACE(CLIENTS,1,'Adam'),2,'Steve'),3,'Jack'),4,'Harvey') FROM PRODUCTS
我应该注意,我实际上不会做Replace(clients, 1, 'adam')
,而是Replace(clients, 1, SELECT CLIENT_NAME FROM CLIENTS WHERE ID = 1)
,但对于这个问题的范围,我或多或少地写了伪代码。
【问题讨论】:
在 SQL Server 2014 中,多重替换是一个很好的解决方案。 使用replace
可能会工作一段时间,但12
会发生什么?你真的想要'AdamSteve'
吗?如果不考虑分隔符,就会发生这种情况。
@HABO 很好,这使得REPLACE()
成为一个更不理想的“解决方案”。
如果您使用Replace( ',' + Clients + ',', ',1,', ',Adam,' ) ...
并在所有替换后修剪前导和尾随逗号,它可以工作,但是很容易出错。更好的是用逗号分隔它并按照 GMB 的答案处理替换。最好不要在列中存储列表。
【参考方案1】:
您不应该以这种格式存储您的数据。应该有一个单独的表,比如product_clients
来存储两个实体之间的关系,每个不同的产品/客户元组有一行。
对于您当前的设计和版本,您最好的选择可能是递归查询,以迭代遍历并将客户端 ID 替换为相应的名称:
with prod as (
select
p.name,
p.clients + ',' as clients,
cast('' as varchar(max)) as new_clients
from products p
union all
select
p.name,
substring(p.clients, charindex(',', p.clients) + 1, len(p.clients)),
p.new_clients + ',' + c.client_name
from prod p
inner join clients c on c.id = left(p.clients, charindex(',', p.clients) - 1)
where charindex(',', p.clients) > 0
)
select name, stuff(max(new_clients), 1, 1, '') as new_clients
from prod
group by name
Demo on DB Fiddle:
姓名 |新客户 :--- | :--------- 一个 |亚当、史蒂夫、杰克、哈维 乙|亚当、杰克、哈维 C |史蒂夫 D |亚当,杰克【讨论】:
感谢您提供的出色 CTE!该表已经存在了一段时间,但我会看看是否可以更改架构以允许您提到的product_clients
表!以上是关于将一个分隔的 id 字段转换为它们的漂亮值 - 嵌套替换是最佳选择吗?的主要内容,如果未能解决你的问题,请参考以下文章