SQL 在逗号分隔行加入

SQL Join on Comma Separated Row

我正在使用 SQL Server 2014,我有一个 table(示例),如下所示:

| Hosts                                  | Description |
|------------------------------------------------------|
| 192.168.0.1,192.168.0.2,192.168.0.3    | Group A     |
| 192.168.0.10,192.168.0.13,192.168.0.15 | Group B     |
| 192.168.0.22                           | Group C     |
|------------------------------------------------------|

我想在新的 table:

中获取这些数据
| Hosts           | Description |
|-------------------------------|
| 192.168.0.1     | Group A     |
| 192.168.0.2     | Group A     |
| 192.168.0.3     | Group A     |
| 192.168.0.10    | Group B     |
| 192.168.0.13    | Group B     |
| 192.168.0.15    | Group B     |
| 192.168.0.22    | Group C     |
|-------------------------------|

我做了什么:

-- List comma separated hosts in a new table (this part is working good)

set @abc = (select hosts from example for xml path(''))
set @xyz = (select replace(replace(@abc,'<HOSTS>',','),'</HOSTS>',''))
select * into newtable from split(@xyz, ',')

--My Join

select newtable.item, example.description
from newtable
left join example on newtable.item like '%' + example.hosts + '%'

但我得到:

| Hosts           | Description |
|-------------------------------|
| 192.168.0.1     | NULL        |
| 192.168.0.2     | NULL        |
| 192.168.0.3     | NULL        |
| 192.168.0.10    | NULL        |
| 192.168.0.13    | NULL        |
| 192.168.0.15    | NULL        |
| 192.168.0.22    | Group C     |
|-------------------------------|

基本上,只有当我的主机值单独位于该行时,我的连接才有效。我希望通过我的查询“'%' + example.hosts + '%'”解决这个问题,但没有。 我尝试使用相同的逻辑使用“交叉应用”和“连接”但没有成功。

如您所见,我在 SQL 方面的知识不多,我觉得我缺少一些基本的东西,尽管我已经坚持了很长时间。

我指望你的帮助,谢谢!

也许你应该做如下的事情:

SELECT Description,Split.a.value('.', 'VARCHAR(max)') 'Hosts' 
FROM  
(
     SELECT Description, CAST ('<X>' + REPLACE(Hosts, ',', '</X><X>') + '</X>' AS XML) AS Data 
     FROM example     
) AS A 
CROSS APPLY Data.nodes ('/X') AS Split(a)

请尝试以下解决方案。

它正在使用 XML 和 XQuery。

要点:

  • 没有派生表或 CTE。
  • CData 部分防止 & 号等字符。
  • XPath 表达式包含 text() 以获得最佳性能。 SQL 服务器特性。

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, Hosts VARCHAR(1024), Description VARCHAR(30));
INSERT INTO @tbl (Hosts, Description) VALUES
('192.168.0.1,192.168.0.2,192.168.0.3', 'Group A'),
('192.168.0.10,192.168.0.13,192.168.0.15', 'Group B'),
('192.168.0.22', 'Group C');
-- DDL and sample data population, end

DECLARE @separator CHAR(1) = ',';

SELECT ID, [Description]
    ,x.value('text()[1]', 'VARCHAR(20)') AS Hosts
FROM @tbl
    CROSS APPLY (SELECT TRY_CAST('<root><r><![CDATA[' + 
          REPLACE(Hosts, @separator, ']]></r><r><![CDATA[') + 
          ']]></r></root>' AS XML)) AS t1(c)
    CROSS APPLY c.nodes ('/root/r') AS t2(x);

输出

+----+-------------+--------------+
| ID | Description |    Hosts     |
+----+-------------+--------------+
|  1 | Group A     |  192.168.0.1 |
|  1 | Group A     |  192.168.0.2 |
|  1 | Group A     |  192.168.0.3 |
|  2 | Group B     | 192.168.0.10 |
|  2 | Group B     | 192.168.0.13 |
|  2 | Group B     | 192.168.0.15 |
|  3 | Group C     | 192.168.0.22 |
+----+-------------+--------------+