我的数据库中的表包含如下值,
TBLFlow
FlowId FlowName ProcessId
------------------------------------------------
F00 Flow1 PID01-PID02-PID03
F01 Flow2 PID01-PID03-PID02
进程的名称列在另一个表中,如下所示
TBLProcess
ProcessId ProcessName
---------------------------
PID01 Process1
PID02 Process2
PID03 Process3
现在,我想将表格中的值拆分为TBLFlow'为了从表格中获取他们的名字' TBLProcess'通过在两个表之间执行连接(最好是'内部连接')。 最后,当我执行查询时,我希望结果如下,
FlowId FlowName ProcessId ProcessName
------------------------------------------------------------------------------
F01 Flow1 PID01-PID02-PID03 Process1-Process2-Process3
F01 Flow1 PID01-PID03-PID02 Process1-Process3-Process2
我正在研究SQL Server 2008,并且希望在单个存储过程中执行此操作。您是否可以帮助我在存储过程中编写查询。
修改
表格' TBLFlow'可以重构如下,
TBLFlow
FlowId FlowName ProcessId
------------------------------------------------
F00 Flow1 PID01
F00 Flow1 PID02
F00 Flow1 PID03
F01 Flow2 PID01
F01 Flow2 PID03
F01 Flow2 PID02
答案 0 :(得分:2)
我想象着这样一个怪物
DECLARE @TBLFlow table (FlowId varchar(20), FlowName varchar(100), ProcessId varchar(1000))
DECLARE @TBLProcess table (ProcessId varchar(20), ProcessName varchar(100))
insert into @TBLFlow values ('F00','Flow1','PID01-PID02-PID03'), ('F01','Flow2','PID01-PID03-PID02')
insert into @TBLProcess values ('PID01','Process1'), ('PID02','Process2'), ('PID03','Process3')
;with c as
(
select
1 as rn,
FlowId,
FlowName,
CHARINDEX('-',ProcessId,1) as Pos,
case when CHARINDEX('-',ProcessId,1)>0 then SUBSTRING(ProcessId,1,CHARINDEX('-',ProcessId,1)-1) else ProcessId end as value,
case when CHARINDEX('-',ProcessId,1)>0 then SUBSTRING(ProcessId,CHARINDEX('-',ProcessId,1)+1,LEN(ProcessId)-CHARINDEX('-',ProcessId,1)) else '' end as ProcessId
from @TBLFlow
union all
select
rn + 1 as rn,
FlowId,
FlowName,
CHARINDEX('-',ProcessId,1) as Pos,
case when CHARINDEX('-',ProcessId,1)>0 then SUBSTRING(ProcessId,1,CHARINDEX('-',ProcessId,1)-1) else ProcessId end as Value,
case when CHARINDEX('-',ProcessId,1)>0 then SUBSTRING(ProcessId,CHARINDEX('-',ProcessId,1)+1,LEN(ProcessId)-CHARINDEX('-',ProcessId,1)) else '' end as ProcessId
from c
where LEN(ProcessId)>0
)
select
f.FlowId,
f.FlowName,
f.ProcessId,
stuff(
(
select '-'+p.ProcessName
from c
inner join @TBLProcess p on p.ProcessId=c.value
where c.flowid=f.flowid
order by c.rn
FOR XML PATH('')
),
1,
1,
''
) as ProcessName
from @TBLFlow f
答案 1 :(得分:0)
你可以试试这个
SELECT F.*,ISNULL(P1.ProcessName,'') + '-' + ISNULL(P2.ProcessName,'') + '-' +
ISNULL(P3.ProcessName,'')
FROM TBLFlow AS F
LEFT JOIN TBLProcess AS P1
ON SUBSTRING(F.ProcessId,0,CHARINDEX('-',F.ProcessId)) = P1.ProcessId
LEFT JOIN TBLProcess AS P2
ON LEFT(RIGHT(F.ProcessId,LEN(F.ProcessId)-CHARINDEX('-',F.ProcessId,1)),
CHARINDEX('- ',RIGHT(F.ProcessId,LEN(F.ProcessId)-
CHARINDEX('-',F.ProcessId,1)),1)-1)
= P2.ProcessId
LEFT JOIN TBLProcess AS P3
ON SUBSTRING(F.ProcessId, LEN(RIGHT(F.ProcessId,LEN(F.ProcessId)-
CHARINDEX('-',F.ProcessId))) + 2,LEN(F.ProcessId)) = P3.ProcessId
答案 2 :(得分:0)
看起来你要求两个单独的查询,一个用ProcessID
列中的非规范化数据解析你的原始表,然后在tblFlow
数据被规范化的情况下再用第二个查询。
tblFlow非规范化查询
如果您无法规范化tblFlow
表中的数据,则表示您使用短划线(PID01-PID02-PID03
)分隔存储在列表中的数据。然后我会按照以下方式进行。
首先,我将创建一个拆分字符串用户定义函数,将ProcessId
字符串分隔为多个列。在线有很多功能,但这是我通常使用的功能:
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;
创建功能后。然后,您将使用CROSS APPLY
进行查询,以将processId
列表传递给该函数。查询将是:
;with cte as
(
select f.flowid, f.flowname, f.processid, s.items processItem
from tblFlow f
cross apply dbo.Split(f.processid, '-') s
)
select *
from cte;
见SQL Fiddle with Demo。这给出了一个结果:
| FLOWID | FLOWNAME | PROCESSID | PROCESSITEM |
-------------------------------------------------------
| F00 | Flow1 | PID01-PID02-PID03 | PID01 |
| F00 | Flow1 | PID01-PID02-PID03 | PID02 |
| F00 | Flow1 | PID01-PID02-PID03 | PID03 |
| F01 | Flow2 | PID01-PID03-PID02 | PID01 |
| F01 | Flow2 | PID01-PID03-PID02 | PID03 |
| F01 | Flow2 | PID01-PID03-PID02 | PID02 |
将ProcessItem
数据拆分为行后,您就可以轻松加入现有表格并生成ProcessNames
的新连续列表。要创建连接列表,可以使用FOR XML PATH
和STUFF。查询将是:
;with cte as
(
select f.flowid, f.flowname, f.processid, s.items processItem
from tblFlow f
cross apply dbo.Split(f.processid, '-') s
)
select distinct c.flowid,
c.flowname,
c.processid,
STUFF(
(SELECT '-' + p.ProcessName
FROM cte c2
inner join tblProcess p
on c2.processItem = p.processId
where c.flowid = c2.flowid
FOR XML PATH (''))
, 1, 1, '') AS ProcessName
from cte c;
见SQL Fiddle with Demo。这给出了一个结果:
| FLOWID | FLOWNAME | PROCESSID | PROCESSNAME |
----------------------------------------------------------------------
| F00 | Flow1 | PID01-PID02-PID03 | Process1-Process2-Process3 |
| F01 | Flow2 | PID01-PID03-PID02 | Process1-Process2-Process3 |
规范化tblFlow
现在,如果tblFlow
数据已经规范化,并且您想创建两个连续列表,一个包含processId
,另一个包含processName
,那么您可以使用以下内容:
select distinct f.flowid,
f.flowname,
STUFF(
(SELECT '-' + f1.Processid
FROM tblFlow f1
where f.flowid = f1.flowid
FOR XML PATH (''))
, 1, 1, '') AS Processid,
STUFF(
(SELECT '-' + p.ProcessName
FROM tblFlow f1
inner join tblProcess p
on f1.ProcessId = p.ProcessId
where f.flowid = f1.flowid
FOR XML PATH (''))
, 1, 1, '') AS ProcessName
from tblFlow f;
见SQL Fiddle with Demo。这会产生一个结果:
| FLOWID | FLOWNAME | PROCESSID | PROCESSNAME |
----------------------------------------------------------------------
| F00 | Flow1 | PID01-PID02-PID03 | Process1-Process2-Process3 |
| F01 | Flow2 | PID01-PID03-PID02 | Process1-Process2-Process3 |