SQL连接表和CONCAT的CASE
我是SQL新手。。。我需要连接两个表,如下所示SQL连接表和CONCAT的CASE,sql,sql-server,sql-server-2016,Sql,Sql Server,Sql Server 2016,我是SQL新手。。。我需要连接两个表,如下所示 Table A | id | Recipe_Web_Codes | |----|--------------------| | 1 | GF VGT | | 2 | | | 3 | VGN | 并生成下表: RESULT | id | Recipe_Web_Codes | Wecode_Fullname | Color
Table A
| id | Recipe_Web_Codes |
|----|--------------------|
| 1 | GF VGT |
| 2 | |
| 3 | VGN |
并生成下表:
RESULT
| id | Recipe_Web_Codes | Wecode_Fullname | Color |
|-------------------------------------------------------|------------------|
| 1 | GF VGT | Gluten Friendly, Vegetarian | #6ca4b6, #ff6038 |
| 2 | | | |
| 3 | VGN | Vegan Friendly | #97002d |
我真的不知道从哪里开始。我尝试了这个方法,但在如何将案例结果连接到单个字段上遇到了困难。我走对了吗
select Recipe_Web_Codes, Webcode_Fullname =
case
when Recipe_Web_Codes like '%VGT%' then (select Webcode_Fullname FROM TABLE_B where Recipe_Web_Code = 'VGT')
when Recipe_Web_Codes like '%VGN%' then (select Webcode_Fullname FROM TABLE_B where Recipe_Web_Code = 'VGN')
when Recipe_Web_Codes like '%GF%' then (select Webcode_Fullname FROM TABLE_B where Recipe_Web_Code = 'GF')
end,
Color =
case
when Recipe_Web_Codes like '%VGT%' then (select Color FROM TABLE_B where Recipe_Web_Code = 'VGT')
when Recipe_Web_Codes like '%VGN%' then (select Color FROM TABLE_B where Recipe_Web_Code = 'VGN')
when Recipe_Web_Codes like '%GF%' then (select Color FROM TABLE_B where Recipe_Web_Code = 'GF')
end
from TABLE_A
编辑:它只是点击我,我错过了一个非常重要的点,为什么我需要聚合这些字符串。生成的表将由另一个单独的进程导出为JSON,因此没有必要提及数据库规范化。此外,这是SQL 2016 SP2,因此我没有可用的字符串_agg功能 您可以使用表的左联接来完成此操作,聚合函数在SQL Server 2017+中工作:
select a.id, a.Recipe_Web_Codes,
string_agg(b.Webcode_Fullname, ', ') Webcode_Fullname,
string_agg(b.Color, ', ') Color
from Table_A a left join Table_B b
on ' ' + a.Recipe_Web_Codes + ' ' like '% ' + b.Recipe_Web_Code + ' %'
group by a.id, a.Recipe_Web_Codes
order by a.id
看。
结果:
您不应该在一列中存储多个值,因此我建议您修复数据模型 也就是说,您可以通过分离字符串并重新聚合来做您想做的事情:
select a.*, b.*
from a outer apply
(select string_agg(b.Webcode_Fullname, ',') as Webcode_Fullname,
string_agg(b.Webcode_Fullname, ',') as Colors
from string_split(a.recipe_web_codes, ' ') s join
b
on s.value = b.Recipe_Web_Code
) b;
非常重要:string_split不能保证值的顺序。如果结果字符串的顺序很重要,则可以使用以下逻辑处理此问题(假设没有重复项):
select a.*, b.*
from a outer apply
(select string_agg(b.Webcode_Fullname, ',') within group (order by charindex(b.Recipe_Web_Codeas, a.recipe_web_codes)) as Webcode_Fullname,
string_agg(b.Webcode_Fullname, ',') within group (order by charindex(b.Recipe_Web_Codeas, a.recipe_web_codes)) as Colors
from string_split(a.recipe_web_codes, ' ') s join
b
on s.value = b.Recipe_Web_Code
) b;
让我再次强调,您应该将精力放在修复数据模型上,为配方web代码创建一个单独的表,每个代码一行
编辑:
旧版本的一个解决方案是递归CTE:
with bs as (
select b.*, row_number() over (order by id) as seqnum
from b
),
cte as (
select a.id, convert(varchar(max), Recipe_Web_Codes) as fullnames, convert(varchar(max), Recipe_Web_Codes) as colors, 1 as ind
from a
union all
select cte.id,
replace(cte.fullnames, bs.Recipe_Web_Code, bs.Webcode_Fullname),
replace(cte.colors, bs.Recipe_Web_Code, bs.color),
1 + cte.ind
from cte join
bs
on cte.ind = bs.seqnum and ind < 10
)
select cte.id, cte.fullnames, cte.colors
from (select cte.*, max(ind) over (partition by id) as max_ind
from cte
) cte
where ind = max_ind ;
这是一个非常糟糕的设计。请学习数据库规范化。由于表A中存在配方代码,您的数据库设计非常奇怪。表A应该引用表B的id。在任何人回答之前,您是否可以更改它?实际上,就您当前显示的字段而言,我不明白您为什么有两个表。关于表/db设计的约定很糟糕,不是我的工作,但这是我必须处理的问题。Darn,我有SQL Server 2016 SP2,我有SQL Server 2016 SP2,所以字符串\u agg对我不可用。同意数据库设计。。。如果你看到整个应用程序的架构,你会感到震惊。看起来很有希望。。。。我不太明白发生了什么,所以我被困在这里:Msg 240,16级,状态1,行1类型在递归查询cte的全名列中的锚和递归部分之间不匹配。Msg 240,级别16,状态1,行1类型在递归查询cte列颜色中的锚和递归部分之间不匹配。确定,通过添加cast replacecte.fullnames、bs.Recipe_Web_代码、bs.Webcode_Fullname作为varcharmax、cast replacecte.colors、bs.Recipe_Web_代码、bs.color作为varcharmax修复了类型匹配,但它似乎只替换了屏幕上的最后一项list@Geto . . . 你看到DB小提琴了吗?所有代码都已替换。递归CTE是有效的。我认为它与数据库上的类型有关,请看这个更新的提琴:顺便说一句,这对我来说都是新的,我对CTE一无所知,我仍然在尝试围绕递归CTE。我仍然不明白为什么它只替换最后一个字段
select a.*, b.*
from a outer apply
(select string_agg(b.Webcode_Fullname, ',') within group (order by charindex(b.Recipe_Web_Codeas, a.recipe_web_codes)) as Webcode_Fullname,
string_agg(b.Webcode_Fullname, ',') within group (order by charindex(b.Recipe_Web_Codeas, a.recipe_web_codes)) as Colors
from string_split(a.recipe_web_codes, ' ') s join
b
on s.value = b.Recipe_Web_Code
) b;
with bs as (
select b.*, row_number() over (order by id) as seqnum
from b
),
cte as (
select a.id, convert(varchar(max), Recipe_Web_Codes) as fullnames, convert(varchar(max), Recipe_Web_Codes) as colors, 1 as ind
from a
union all
select cte.id,
replace(cte.fullnames, bs.Recipe_Web_Code, bs.Webcode_Fullname),
replace(cte.colors, bs.Recipe_Web_Code, bs.color),
1 + cte.ind
from cte join
bs
on cte.ind = bs.seqnum and ind < 10
)
select cte.id, cte.fullnames, cte.colors
from (select cte.*, max(ind) over (partition by id) as max_ind
from cte
) cte
where ind = max_ind ;