2014-10-08 89 views
1

我搜索了很多论坛和网站,一直没能找到解决方案。也许我不是在寻找正确的东西 - 但任何方向和援助将不胜感激!传递多个字符串和多个值作为参数

我想加入两个表格:UserDataServiceStatsUserData由以下各列和样本数据:

Title   Application 
------------ ------------- 
Site Manager KB1245;KB3256 
FTP_Viewer  FTP1536 

ServiceStats由以下各列和样本数据:

ApplicationName Vendor 
--------------- ------------ 
KB1245    Kronos 
KB3256    Kronos2 
FTP1536   File Manager 

当加入我需要得到类似以下的输出表:

Site Manager KB1245 Kronos 
Site Manager KB3256 Kronos2 
FTP_Viewer FTP1536 File Manager 

我的问题是让连接阅读和识别何时有多个ApplicationNamesTitle

再次 - 感谢任何帮助和指导。

+3

您已在'UserData.Application'列中分隔数据。 **不要这样做** **字段中的分隔数据是常见的数据库反模式。修正模式,使每个值在数据库中都有自己的位置,突然间,这个连接问题变得很容易。 – 2014-10-08 19:53:29

+0

我已经与团队联系过了 - 但不幸的是我无法改变它。还有其他几项基于该分隔字段的项目。 – user3813523 2014-10-08 20:32:50

回答

0

我可以削减OP一些松懈。作为开发者,我们不得不处理由他人做出的不太理想的决定。 OP应该搜索的是如何分割分隔字符串,在StackOverflow中有多个字符串。

我的解决办法:

;WITH 
    cte1 AS (
     SELECT Title, 
       REPLACE(Application,' ','') + ';' AS Application 
     FROM UserData 
    ), 
    cte2 AS (
     SELECT Title, 
       LEFT(Application,CHARINDEX(';',Application)-1)  AS ApplicationName, 
       STUFF(Application,1,CHARINDEX(';',Application),'') AS RemainingApp 
     FROM cte1 
     UNION ALL 
     SELECT Title, 
       LEFT(RemainingApp,CHARINDEX(';',RemainingApp)-1), 
       STUFF(RemainingApp,1,CHARINDEX(';',RemainingApp),'') 
     FROM cte2 
     WHERE LEN(RemainingApp) > 0 
    ) 

SELECT c2.Title, 
     c2.ApplicationName, 
     s.Vendor 
FROM cte2 c2 
INNER JOIN ServiceStats s ON c2.ApplicationName = s.ApplicationName 
+0

我必须做一些调整才能在我的具体实例中工作 - 但这确实给了我正确的方向。 – user3813523 2014-10-09 13:39:32

0

我更喜欢使用一个表值函数,让我加入到它。这也使我的代码更小,当我不得不使用它:

ALTER FUNCTION [dbo].[Split](@String VARCHAR(8000), @Delimiter CHAR(1))  
RETURNS @temptable TABLE (item VARCHAR(8000))  
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(Item) VALUES(@slice)  
     SET @String = RIGHT(@String,len(@String) - @idx)  
     IF len(@String) = 0 break  
    END 
    RETURN  
END 

然后使用它:

SELECT * FROM dbo.Split('1;2;3;4;5',';') 

它的工作原理就像一个表,你甚至可以加入到它:

SELECT * 
FROM dbo.Split('1;2;3;4;5',';') a 
INNER JOIN MyTable b ON a.item = b.Field1 
相关问题