SQL Server 2012:拆分逗号分隔ProductID关联两表获取目标InvoiceData行
解决方案:SQL Server 2012 拆分逗号分隔字段并比对匹配
哦,SQL Server 2012确实没有官方的STRING_SPLIT函数,我之前也遇到过类似的问题,给你几个可行的解决方案:
方法一:创建自定义字符串拆分函数
先创建一个可复用的拆分函数,以后处理类似场景都能直接用:
CREATE FUNCTION dbo.SplitString ( @InputString NVARCHAR(MAX), @Delimiter NVARCHAR(5) ) RETURNS @SplitTable TABLE (Value NVARCHAR(MAX)) AS BEGIN DECLARE @StartIndex INT, @EndIndex INT SET @StartIndex = 1 -- 确保字符串末尾有分隔符,避免遗漏最后一个值 IF SUBSTRING(@InputString, LEN(@InputString), 1) <> @Delimiter BEGIN SET @InputString = @InputString + @Delimiter END WHILE CHARINDEX(@Delimiter, @InputString) > 0 BEGIN SET @EndIndex = CHARINDEX(@Delimiter, @InputString) INSERT INTO @SplitTable(Value) VALUES(SUBSTRING(@InputString, @StartIndex, @EndIndex - @StartIndex)) SET @InputString = SUBSTRING(@InputString, @EndIndex + 1, LEN(@InputString)) END RETURN END GO
然后用这个函数关联两张表,筛选出符合条件的发票记录:
SELECT DISTINCT i.* FROM InvoiceData i CROSS APPLY dbo.SplitString(i.ProductID, ',') ip INNER JOIN OrderData o CROSS APPLY dbo.SplitString(o.ProductID, ',') op ON ip.Value = op.Value
这里加DISTINCT是为了避免同一条发票记录因为多个匹配的ProductID而重复出现,完全满足你“只要有一个ProductID匹配就保留”的需求。
方法二:直接用XML解析(无需创建函数)
如果不想创建函数,也可以直接用XML解析的方式在查询里拆分字符串,适合临时查询场景:
SELECT DISTINCT i.* FROM InvoiceData i CROSS APPLY ( SELECT x.value('.', 'NVARCHAR(MAX)') AS ProductID FROM (SELECT CAST('<item>' + REPLACE(i.ProductID, ',', '</item><item>') + '</item>' AS XML) AS xmlData) t CROSS APPLY t.xmlData.nodes('item') AS n(x) ) ip INNER JOIN OrderData o CROSS APPLY ( SELECT x.value('.', 'NVARCHAR(MAX)') AS ProductID FROM (SELECT CAST('<item>' + REPLACE(o.ProductID, ',', '</item><item>') + '</item>' AS XML) AS xmlData) t CROSS APPLY t.xmlData.nodes('item') AS n(x) ) op ON ip.ProductID = op.ProductID
这个方法的核心是把逗号分隔的字符串转换成XML节点,再通过nodes()方法拆分出每个ProductID,最后做关联匹配。
补充:用EXISTS优化性能
如果你的数据量较大,用EXISTS替代INNER JOIN会更高效,既能避免重复数据,又能减少不必要的关联操作:
SELECT i.* FROM InvoiceData i WHERE EXISTS ( SELECT 1 FROM ( SELECT x.value('.', 'NVARCHAR(MAX)') AS ProductID FROM (SELECT CAST('<item>' + REPLACE(i.ProductID, ',', '</item><item>') + '</item>' AS XML) AS xmlData) t CROSS APPLY t.xmlData.nodes('item') AS n(x) ) ip WHERE EXISTS ( SELECT 1 FROM OrderData o CROSS APPLY ( SELECT x.value('.', 'NVARCHAR(MAX)') AS ProductID FROM (SELECT CAST('<item>' + REPLACE(o.ProductID, ',', '</item><item>') + '</item>' AS XML) AS xmlData) t CROSS APPLY t.xmlData.nodes('item') AS n(x) ) op WHERE op.ProductID = ip.ProductID ) )
这样就能精准返回InvoiceData中至少有一个ProductID存在于OrderData中的行,你提到的发票编号123、3334、3456和3435都会被包含进来。
内容的提问来源于stack exchange,提问作者Sunil
相关产品推荐
相关产品推荐

