use*_*458 2 sql t-sql sql-server sql-server-2008
我有这样Table1的列:
+--+------+
|ID|Name |
+--+------+
|1 |MSSQL |
+--+------+
|2 |MySQl |
+--+------+
|3 |Oracle|
+--+------+
Run Code Online (Sandbox Code Playgroud)
在Table2,我有一个专栏
+------------+
|Databasename|
+------------+
|1,3 |
+------------+
|2 |
+------------+
|1,2 |
+------------+
Run Code Online (Sandbox Code Playgroud)
我的输出应该是:
+------------+
|Databasename|
+------------+
|MSSQL,Oracle|
+------------+
|MySQL |
+------------+
|MSSQL,MYSQL |
+------------+
Run Code Online (Sandbox Code Playgroud)
我怎么得到这个,我需要查询这个..
您要求分割功能,但您不必分割您的值以获得所需的结果.
此查询使用for xml连接值的技巧在相关子查询中构建逗号分隔的名称列表.它用于确定每行中like使用的值.Table1Table2
select (
select ', '+T1.Name
from Table1 as T1
where ','+T2.Databasename+',' like '%,'+cast(T1.ID as varchar(10))+',%'
for xml path(''), type
).value('substring(text()[1], 3)', 'varchar(max)') as Databasenames
from Table2 as T2
Run Code Online (Sandbox Code Playgroud)
首先,您最好的解决方案是不将数据存储在数据库中以逗号分隔的列表中.您应该考虑修复表结构.
如果无法更改表结构,则需要将列表中的数据拆分为行以指定正确的名称.分割数据后,您可以将数据连接回列表.
split您可以在线找到许多不同的功能,但这是我通常使用的版本:
CREATE FUNCTION [dbo].[Split](@String varchar(MAX), @Delimiter char(1))
returns @temptable TABLE (items varchar(MAX))
as
begin
declare @idx int
declare @slice varchar(8000)
select @idx = 1
if len(@String)<1 or @String is null return
while @idx!= 0
begin
set @idx = charindex(@Delimiter,@String)
if @idx!=0
set @slice = left(@String,@idx - 1)
else
set @slice = @String
if(len(@slice)>0)
insert into @temptable(Items) values(@slice)
set @String = right(@String,len(@String) - @idx)
if len(@String) = 0 break
end
return
end;
Run Code Online (Sandbox Code Playgroud)
为了得到你的结果,我将从应用split函数开始,row_number()因为我没有看到与每一行相关联的唯一键.如果每行都有一个唯一的密钥,那么您将不需要row_number():
;with cte as
(
select rn, name, id
from
(
select row_number() over(order by (select 1)) rn,
databasename
from table2
) t2
cross apply dbo.split(t2.databasename, ',') i
inner join table1 t1
on i.items = t1.id
)
select *
from cte
Run Code Online (Sandbox Code Playgroud)
此查询将以逗号分隔的列表分为以下内容:
| RN | NAME | ID |
--------------------
| 1 | MSSQL | 1 |
| 1 | Oracle | 3 |
| 2 | MySQl | 2 |
| 3 | MSSQL | 1 |
| 3 | MySQl | 2 |
Run Code Online (Sandbox Code Playgroud)
一旦你有正确的多行数据name,你就可以使用STUFF()并将FOR XML PATH它连接到列表中.您完全查询将类似于:
;with cte as
(
select rn, name, id
from
(
select row_number() over(order by (select 1)) rn,
databasename
from table2
) t2
cross apply dbo.split(t2.databasename, ',') i
inner join table1 t1
on i.items = t1.id
)
select
STUFF(
(SELECT ', ' + c2.name
FROM cte c2
where c1.rn = c2.rn
order by c2.id
FOR XML PATH (''))
, 1, 1, '') Databasename
from cte c1
group by c1.rn
order by c1.rn;
Run Code Online (Sandbox Code Playgroud)
完整查询的结果是:
| DATABASENAME |
------------------
| MSSQL, Oracle |
| MySQl |
| MSSQL, MySQl |
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25712 次 |
| 最近记录: |