我有以下表格:
Orders
id int
orderName varchar(5000)
Communication
body varchar(5000)
attachment varchar(5000)
样品订单数据:
id name
132 ordGD
589 ordPG
6321 ordMF
示例通讯数据:
body attachment
body1 132,589,6321
我想创建一个存储过程,从Communication
在SP中,输入@attachment varchar(5000)
包含多个orderid,逗号分隔,引用Orders表
问题:我希望OrderName根据与@Attachment匹配的订单中的Orderid
答案 0 :(得分:1)
对于此类流程,您需要split
attachment
列中的数据。我使用与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
由于这会返回一个表,您可以加入数据。所以你的查询看起来像这样:
select o.id,
o.name,
c.body
from orders o
left join
(
select c.body, s.items as o_id
from communications c
cross apply dbo.split(c.attachment, ',') s
) c
on o.id = c.o_id
如果您只想使用正确的名称替换attachment
字段中的值,则可以一步使用Split
函数和CTE
:
;with cte as (
select o.id,
o.name,
c.body
from orders o
left join
(
select c.body, s.items as o_id
from communications c
cross apply dbo.split(c.attachment, ',') s
) c
on o.id = c.o_id
)
select distinct c2.body,
stuff((select distinct ', ' + c1.name
from cte c1
where c2.body = c1.body
for XML path('')),1,1,'') attachment
from cte c2
答案 1 :(得分:1)
正如其他人所评论的那样,正确的解决方案是将数据库模式更改为具有原子字段的规范化模式。
当前架构的解决方案是首先使用任何multiple ways available将附件字段拆分为订单号列表。下一步是将结果与id上的Orders表连接以获得结果。第三步是concatenate the names back into a list。请参阅提供的链接以了解拆分和加入的说明。
以下是执行3个步骤的代码段:
WITH
-- Numbers table for split logic
L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
L1 AS(SELECT 1 AS c FROM L0 AS A, L0 AS B),
L2 AS(SELECT 1 AS c FROM L1 AS A, L1 AS B),
L3 AS(SELECT 1 AS c FROM L2 AS A, L2 AS B),
Numbers AS(SELECT ROW_NUMBER() OVER(ORDER BY c) AS n FROM L3),
-- The join query for step 2
bodyOrders AS
(SELECT body,
o1.name orderName
FROM Numbers AS nums
INNER JOIN Communication AS valueTable
ON nums.n <= CONVERT(int, LEN(valueTable.attachment))
AND SUBSTRING(N',' + valueTable.attachment, n, 1) = N','
INNER JOIN Orders o1
ON LTRIM(RTRIM(SUBSTRING(valueTable.attachment, nums.n,
charindex(N',', valueTable.attachment + N',', nums.n) - nums.n))) = o1.id
)
-- Concatenation logic for step 3
SELECT body,
stuff( (SELECT ','+ orderName
FROM bodyOrders b2
WHERE b2.body = b1.body
ORDER BY orderName
FOR XML PATH(''), TYPE).value('.', 'varchar(5000)')
,1,1,'')
AS orderNumbers
FROM bodyOrders b1
GROUP BY body;
此代码段未提供针对大型数据集执行此操作的最佳或高效方法。这只是一个例子,说明如果你必须沿着这条路走下去的话。