我有一个SQL Server表,其中包含多行,如下所示。每行都有一个定界符“ ^”。我想从每一行中创建一个单独的列。
假设这是原始表格:
源表(仅一列)
StringVal
-------------------------------------------------
57^H:\ ^ 200^Test ^2018-09-19 08:20:01.000
8^T:\ ^ 88^Test1 ^2018-09-1 08:00:01.000
33^D:\ ^ 40^Test2 ^2018-10-1 08:10:01.000
我的要求是使用上表在输出中选择以下列
目标表(具有5列)
FreeSpace | Total | Drive | Server | Date
----------+----------+-------+--------+--------------------------
57 | 200 | H:\ | Test | 2018-09-19 08:20:01.000
8 | 88 | T:\ | Test1 | 2018-09-1 08:00:01.000
33 | 40 | D:\ | Test2 | 2018-10-1 08:10:01.000
注意:源表中的字符串也包含空值。该字符串还包含许多空白位置,没有任何顺序。所以这也需要处理。
我尝试使用字符串函数,但是它只给我第一个定界符的值,并进一步跳过。
SELECT
Substring(string, 1, Charindex('^', string) - 1) as Name,
Substring(string, 4, Charindex('^', n) + 3) as Name1
FROM
Sourcetable
我期望输出如下,带有5个不同的列
FreeSpace | Total | Drive | Server | Date
----------+----------+-------+--------+--------------------------
57 | 200 | H:\ | Test | 2018-09-19 08:20:01.000
8 | 88 | T:\ | Test1 | 2018-09-1 08:00:01.000
33 | 40 | D:\ | Test2 | 2018-10-1 08:10:01.000
答案 0 :(得分:1)
您应该将当前的单列表转储到文本文件,然后使用SQL Server的导入向导重新导入。您要使用的定界符为:
\s*^\s*
如果向导不接受此分隔符,则可能必须预处理文件。您可以进行\s*^\s*
的正则表达式替换,并仅用逗号替换。然后,使用逗号作为分隔符,通过向导导入到SQL Server。
答案 1 :(得分:1)
怎么样
WITH CTE AS
(
SELECT *
FROM Strings S CROSS APPLY
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) RN,
Value
FROM STRING_SPLIT(Str, '^')
) SP
)
SELECT ID,
Str,
MAX(CASE WHEN RN = 1 THEN Value END) FreeSpace,
MAX(CASE WHEN RN = 2 THEN Value END) DriveLetter,
MAX(CASE WHEN RN = 3 THEN Value END) Total,
MAX(CASE WHEN RN = 4 THEN Value END) Server,
MAX(CASE WHEN RN = 5 THEN Value END) [Date]
FROM CTE
GROUP BY ID,
Str;
答案 2 :(得分:0)
我的输入
select * from StringVal
StringVal
57^H:\ ^ 200^Test ^2018-09-19 08:20:01.000
8^T:\ ^ 88^Test1 ^2018-09-1 08:00:01.000
33^D:\ ^ 40^Test2 ^2018-10-1 08:10:01.000
查询
;with cte
as (
select
CONVERT (varchar (255), StringVal) StringVal
, convert (varchar (255), StringVal) want -- 'want' means wanted column.
, ROW_NUMBER () over (partition by StringVal order by (select null)) id
-- Row id. Based on original value. for track/count the '^'.
from StringVal
union all
select
CONVERT (varchar (255), StringVal)
, convert ( varchar (255)
, stuff (
want, CHARINDEX ('^', want),1
,choose (id, '</FreeSpace ><Drive>','</Drive><Total>', '</Total><Server>','</Server><Date>')
-- Replace the '^' by XML tags based on column's order.
)
)
, id + 1
from cte
where want like '%^%'
)
select
FreeSpace.value('.', 'varchar (255)') FreeSpace
, Total.value('.', 'varchar (255)') Total
, Drive.value('.', 'varchar (255)') Drive
, Server.value('.', 'varchar (255)') Server
, Date.value('.', 'varchar (255)') Date
from (
select convert(xml, '<StringVal><FreeSpace>' + want + '</Date></StringVal>') StringVal
from cte where id = 5
) xml
cross apply -- I'm not good in XML. so I need lot xml.nodes.
xml.StringVal.nodes('/StringVal/FreeSpace') FreeSpace(FreeSpace)
cross apply
xml.StringVal.nodes('/StringVal/Total') Total(Total)
cross apply
xml.StringVal.nodes('/StringVal/Drive') Drive(Drive)
cross apply
xml.StringVal.nodes('/StringVal/Server') Server(Server)
cross apply
xml.StringVal.nodes('/StringVal/Date') Date(Date)
最终输出
FreeSpace Total Drive Server Date
8 88 T:\ Test1 2018-09-1 08:00:01.000
57 200 H:\ Test 2018-09-19 08:20:01.000
33 40 D:\ Test2 2018-10-1 08:10:01.000