我知道有很多关于递归自联接的问题,但是它们主要是在分层数据结构中,如下所示:
ID | Value | Parent id
-----------------------------
但我想知道是否有办法在特定情况下执行此操作,我不一定拥有父ID。我最初加载文件时,我的数据将如下所示。
ID | Line |
-------------------------
1 | 3,Formula,1,2,3,4,...
2 | *,record,abc,efg,hij,...
3 | ,,1,x,y,z,...
4 | ,,2,q,r,s,...
5 | 3,Formula,5,6,7,8,...
6 | *,record,lmn,opq,rst,...
7 | ,,1,t,u,v,...
8 | ,,2,l,m,n,...
基本上,它是一个CSV文件,其中表中的每一行都是文件中的一行。第1行和第5行标识对象标题,第3,第4,第7和第8行标识属于该对象的行。对象标题行只能有40个属性,这就是为什么对象在CSV文件的多个部分中被分解的原因。
我想做的是拿表,将记录#列分开,然后多次连接它,这样就可以达到这样的目的:
ID | Line |
-------------------------
1 | 3,Formula,1,2,3,4,5,6,7,8,...
2 | *,record,abc,efg,hij,lmn,opq,rst
3 | ,,1,x,y,z,t,u,v,...
4 | ,,2,q,r,s,l,m,n,...
我知道它可能有可能,我只是不确定从哪里开始。我最初的想法是创建一个视图来分隔视图中的第一列和第二列,并使用视图作为在这两列上以重复方式连接的方式。但是,我有一些问题:
的
ID | Line |
-------------------------
1 | 3,Formula,1,2,3,4,...
2 | *,record,abc,efg,hij,...
3 | ,,1,x,y,z,...
4 | ,,2,q,r,s,...
5 | 3,Formula,5,6,7,8,...
6 | *,record,lmn,opq,rst,...
7 | ,,1,t,u,v,...
8 | ,,2,l,m,n,...
9 | ,4,Data,1,2,3,4,...
10 | *,record,lmn,opq,rst,...
11 | ,,1,t,u,v,...
在上面的例子中,我的计划可以通过匹配记录值1来连接第9行中Data对象中的行和Formula对象的第一行。
更新
我知道这有点令人困惑。我尝试用C#做了这个,但我基本上写了一个递归的正确解析器来解析特定的文件格式,它只需要很长时间,因为我之后必须在数据库中获取它并且它对于实体框架来说太多了。转换一个文件只需要几个小时,因为这些文件过大。
无论哪种方式,@ Nolan Shang的结果与我想要的最接近。唯一的区别是这(遗憾的是格式错误):
+----+------------+------------------------------------------+-----------------------+
| ID | header | x | value
|
+----+------------+------------------------------------------+-----------------------+
| 1 | 3,Formula, | ,1,2,3,4,5,6,7,8 |3,Formula,1,2,3,4,5,6,7,8 |
| 2 | ,, | ,1,x,y,z,t,u,v | ,1,x,y,z,t,u,v |
| 3 | ,, | ,2,q,r,s,l,m,n | ,2,q,r,s,l,m,n |
| 4 | *,record, | ,abc,efg,hij,lmn,opq,rst |*,record,abc,efg,hij,lmn,opq,rst |
| 5 | ,4, | ,Data,1,2,3,4 |,4,Data,1,2,3,4 |
| 6 | *,record, | ,lmn,opq,rst | ,lmn,opq,rst |
| 7 | ,, | ,1,t,u,v | ,1,t,u,v |
+----+------------+------------------------------------------+-----------------------------------------------+
答案 0 :(得分:0)
我同意将其导出为脚本语言并在那里执行会更好。这将是TSQL的大量工作。
您已经暗示您还没有其他可能出现的情况,所以我显然无法提供全面的解决方案。我猜这不是你需要在重复的基础上快速完成的事情。更多的是一次性转型,因此性能不是问题。
一种方法是对可能的识别子字符串的硬编码表执行LEFT JOIN
,如:
3,Formula,
*,record,
,,1,
,,2,
,4,Data,
看起来它几乎必须是人为选择和硬编码的,因为我找不到可用于仅选择这些子字符串的可靠模式。
然后从这个人工创建的表(或派生表,或CTE)中选择并使用LIKE
LEFT JOIN到您的实际表中,以获取使用这些值作为其起始子字符串的所有行,删除起始字符以获取字符串的其余部分,并使用STUFF..FOR XML trick构建所需的Line
。
如何获取ID列取决于您想要的内容,例如在第二个示例中,我不知道您想要,4,Data,...
行的ID。你想要5,因为它是结果中的下一个数字,还是你想要9因为那个子串的第一个出现的ID?相应的代码。如果你想要5,那就是ROW_NUMBER()
。如果您想要9,则可以将ID列添加到您在此方法开始时创建的仿真表中。
答案 1 :(得分:0)
这是一个示例,但您需要一些不同的示例。 这是因为我使用第二个逗号作为组头的值,所以,1和,, 2将被视为同一组,如果你可以使用父ID来表示一个组会更好
DECLARE @testdata TABLE(ID int,Line varchar(8000))
INSERT INTO @testdata
SELECT 1,'3,Formula,1,2,3,4,...' UNION ALL
SELECT 2,'*,record,abc,efg,hij,...' UNION ALL
SELECT 3,',,1,x,y,z,...' UNION ALL
SELECT 4,',,2,q,r,s,...' UNION ALL
SELECT 5,'3,Formula,5,6,7,8,...' UNION ALL
SELECT 6,'*,record,lmn,opq,rst,...' UNION ALL
SELECT 7,',,1,t,u,v,...' UNION ALL
SELECT 8,',,2,l,m,n,...' UNION ALL
SELECT 9,',4,Data,1,2,3,4,...' UNION ALL
SELECT 10,'*,record,lmn,opq,rst,...' UNION ALL
SELECT 11,',,1,t,u,v,...'
;WITH t AS(
SELECT *,REPLACE(SUBSTRING(t.Line,LEN(c.header)+1,LEN(t.Line)),',...','') AS data
FROM @testdata AS t
CROSS APPLY(VALUES(LEFT(t.Line,CHARINDEX(',',t.Line, CHARINDEX(',',t.Line)+1 )))) c(header)
)
SELECT MIN(ID) AS ID,t.header,c.x,t.header+STUFF(c.x,1,1,'') AS value
FROM t
OUTER APPLY(SELECT ','+tb.data FROM t AS tb WHERE tb.header=t.header FOR XML PATH('') ) c(x)
GROUP BY t.header,c.x
+----+------------+------------------------------------------+-----------------------------------------------+ | ID | header | x | value | +----+------------+------------------------------------------+-----------------------------------------------+ | 1 | 3,Formula, | ,1,2,3,4,5,6,7,8 | 3,Formula,1,2,3,4,5,6,7,8 | | 3 | ,, | ,1,x,y,z,2,q,r,s,1,t,u,v,2,l,m,n,1,t,u,v | ,,1,x,y,z,2,q,r,s,1,t,u,v,2,l,m,n,1,t,u,v | | 2 | *,record, | ,abc,efg,hij,lmn,opq,rst,lmn,opq,rst | *,record,abc,efg,hij,lmn,opq,rst,lmn,opq,rst | | 9 | ,4, | ,Data,1,2,3,4 | ,4,Data,1,2,3,4 | +----+------------+------------------------------------------+-----------------------------------------------+