我有一个包含竖线分隔值的 varchar 列的表
例如:
Row 1 Column 1 = a|b|e|gg|foo
Row 2 Column 1 = oV|foo|do
Row 3 Column 1 = boop
我如何查询它以返回类似的东西?重复是可以的。
结果:
column
a
b
e
gg
foo
foo
oV
do
boop
我意识到这不是最优的,但我的手被当前的模式束缚了
我有一个包含竖线分隔值的 varchar 列的表
例如:
Row 1 Column 1 = a|b|e|gg|foo
Row 2 Column 1 = oV|foo|do
Row 3 Column 1 = boop
我如何查询它以返回类似的东西?重复是可以的。
结果:
column
a
b
e
gg
foo
foo
oV
do
boop
我意识到这不是最优的,但我的手被当前的模式束缚了
如果您无法更改当前模式,则可以创建一个拆分函数:
然后你可以使用 an
outer apply
来加入你的表:这将产生以下结果:
请参阅带有演示的 SQL Fiddle
或者,如果您不想使用拆分函数,则可以使用 CTE 执行此操作:
请参阅带有演示的 SQL Fiddle
假设您的数据包含普通的字母数字字符并且没有任何东西会破坏 XML,您可以使用此查询执行一些文本操作以使您的数据看起来像 XML,然后执行 XQuery 来分割列。
MS SQL Server 2012 架构设置:
结果(SQL 小提琴):
比使用 XML 或函数更快的方法是使用计数表。以下代码改编自我最强烈推荐的一篇优秀的 Jeff Moden 文章。
代码有点复杂,但性能明显更好,尤其是当您需要解析的行数增加时。
前几个 CTE(E1、E2 和 E4)只是在设置计数表。然后 cteTally CTE 动态生成最佳计数表长度(表中最长字符串的长度)。然后,cteStart 找到所有的分离点。您的数据集的结果如下所示:
解释这个有点棘手,因为该过程在第一个位置添加了一个伪分隔符(如果尚不存在),这是一个单索引字符串。因此,第 1、2 和 3 行的 N1 = 1。3 不再有分隔符。1 在位置 3、5、7 和 10 处有额外的分隔符,再次注意到字符“a”实际上位于此设置中的位置 2。
无论如何,最终查询会进行实际拆分并返回所需的数据集。
计数表拆分是字符串拆分问题的最佳非 CLR 解决方案。如果您的行少于大约 10,000 行,CTE 理货表会更快,但在大约 10K 标记之后,标准理货表解决方案会变得更好。CLR 字符串拆分模块会比两者都快,但我知道很多商店都对安装 CLR 模块犹豫不决。