如何基于模式拆分文本值,并使用TSQL在表中返回结果
我有这个字符串,它存储在一个文本字段中。此后,存储此信息的过程发生了变化,但我需要这些遗留信息如何基于模式拆分文本值,并使用TSQL在表中返回结果,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有这个字符串,它存储在一个文本字段中。此后,存储此信息的过程发生了变化,但我需要这些遗留信息 23.06.17 - As per quote #8918.1. 7m Swing STage to Positon 1. 05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off. 05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off
23.06.17 - As per quote #8918.1. 7m Swing STage to Positon 1.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
06.07.17 - Completion of Swing Stage to Positon 4.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.
如何按日期字段将文本拆分为结果表,以便为每个新日期显示包含日期的新行。那么在上面的例子中,会有6行吗
这就是我提出的概念证明:
DECLARE @MEMO VARCHAR(MAX)
SET @MEMO = '23.06.17 test 1 24.06.17 test 2 25.06.17 test 3'
DECLARE @COUNTER INT
SET @COUNTER=0
DECLARE @WORD VARCHAR(40)
SET @WORD = ''
DECLARE @DATE VARCHAR(10)
SET @DATE = ''
DECLARE @LINE VARCHAR(500)
SET @LINE = ''
WHILE @COUNTER <= LEN(@MEMO)+1 BEGIN
IF SUBSTRING(@MEMO, @COUNTER, 1) != ' ' BEGIN
--Builds each character into a string.
SET @WORD = @WORD + SUBSTRING(@MEMO, @COUNTER, 1)
-- When we come across a space, assume the previous character is now a whole word.
END ELSE IF SUBSTRING(@MEMO, @COUNTER, 1) = ' ' BEGIN
IF @WORD NOT LIKE '[0-9][0-9].[0-9][0-9].[0-9][0-9]' BEGIN
SET @LINE = @LINE + ' ' + @WORD
SET @WORD = ''
--If that word is a date string format then save it and reset.
END ELSE IF @WORD LIKE '[0-9][0-9].[0-9][0-9].[0-9][0-9]' BEGIN
SET @DATE = @WORD
SET @LINE = ''
SET @WORD = ''
PRINT 'DATE: ' + @DATE
END
IF LTRIM(@LINE) != '' BEGIN
PRINT 'LINE: ' + LTRIM(@LINE)
END
END
SET @COUNTER = @COUNTER + 1
END
例如,最终目标基本上就是这样
╔═══╦════════════╦═════════════╗
║ ║ Date ║ Value ║
╠═══╬════════════╬═════════════╣
║ 1 ║ 2017-06-23 ║ Test 1 ║
║ 2 ║ 2017-06-24 ║ Test 2 ║
║ 3 ║ 2017-06-25 ║ Test 3 ║
╚═══╩════════════╩═════════════╝
编辑-已更正输入错误
一种方法是将字符串解析为单词,然后重新构造
我使用了一个表值函数来分割字符串,但很容易转换为一种无需自定义项的内嵌方法
范例
返回
解析/拆分UDF(如果感兴趣)
此解决方案基于基于递归CTE的专门构建iTVF 功能代码:
ALTER FUNCTION dbo.ParseLegacyInfo
/* ===================================================================
Created to parse the text information from legacy system.
==================================================================== */
(
@TextString VARCHAR(8000)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH
cte_rSplit AS (
SELECT
LineNum = 1,
ParsedString = SUBSTRING(@TextString, 1, dl.DateLocation + 7),
StringRemain = SUBSTRING(@TextString, dl.DateLocation + 8, 8000)
FROM
( VALUES(ISNULL(NULLIF(PATINDEX('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%', STUFF(@TextString, 1, 8, '')), 0), 8000)) ) dl (DateLocation)
UNION ALL
SELECT
LineNum = rs.LineNum + 1,
ParsedString = SUBSTRING(rs.StringRemain, 1, dl.DateLocation + 7),
StringRemain = SUBSTRING(rs.StringRemain, dl.DateLocation + 8, 8000)
FROM
cte_rSplit rs
CROSS APPLY ( VALUES(ISNULL(NULLIF(PATINDEX('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%', STUFF(rs.StringRemain, 1, 8, '')), 0), 8000)) ) dl (DateLocation)
WHERE
rs.StringRemain LIKE '%[0-9][0-9].[0-9][0-9].[0-9][0-9]%'
)
SELECT
rs.LineNum,
[Date] = CONVERT(DATE, LEFT(rs.ParsedString, 8), 4),
TextValue = SUBSTRING(rs.ParsedString, 9, 8000)
FROM
cte_rSplit rs;
GO
一些测试数据
IF OBJECT_ID('tempdb..#LegacyInfo', 'U') IS NOT NULL
DROP TABLE #LegacyInfo;
CREATE TABLE #LegacyInfo (
id INT NOT NULL IDENTITY(1, 1),
TextData VARCHAR(8000) NOT NULL
);
INSERT #LegacyInfo (TextData) VALUES
('23.06.17 - As per quote #8918.1. 7m Swing STage to Positon 1.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
06.07.17 - Completion of Swing Stage to Positon 4.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.'),
('23.06.17 - As per quote #8918.1. 7m Swing STage to Positon 1.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
06.07.17 - Completion of Swing Stage to Positon 4.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.'),
('31.12.17 - This is just a test...'),
('01.01.17 - Line 1
Some other text following line 1.
22.02.17 - Line 2
More stuff about line 2.');
最后一个查询
SELECT
li.id, LineNum, Date, TextValue
FROM
#LegacyInfo li
CROSS APPLY dbo.ParseLegacyInfo(li.TextData);
结果。。。注意:原来的甲壳返回和线饲料仍然在tact
我不会在数据库中处理这个问题,我会导出到Java或Perl之类的工具,然后在那里进行工作。结果将在crystal报表中使用,所以我要么在该程序中进行,要么在SQL中进行。不过,我的第一个解决方案是使用SQL。谢谢你你能保证在每个条目的开头都会有一个格式为nn.nn.nn的子字符串,其中n是一个数字字符吗?此外,每个条目是否应以表格nn.nn.nn-开头?在你的6个示例条目中,有4个也是以破折号开头的,但其他2个不是。是的,回答nn.nn.nn问题。后面的破折号可以视为文本。示例中的每个日期前是否有换行符?char13+char10或仅char10或仅char13
ALTER FUNCTION dbo.ParseLegacyInfo
/* ===================================================================
Created to parse the text information from legacy system.
==================================================================== */
(
@TextString VARCHAR(8000)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH
cte_rSplit AS (
SELECT
LineNum = 1,
ParsedString = SUBSTRING(@TextString, 1, dl.DateLocation + 7),
StringRemain = SUBSTRING(@TextString, dl.DateLocation + 8, 8000)
FROM
( VALUES(ISNULL(NULLIF(PATINDEX('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%', STUFF(@TextString, 1, 8, '')), 0), 8000)) ) dl (DateLocation)
UNION ALL
SELECT
LineNum = rs.LineNum + 1,
ParsedString = SUBSTRING(rs.StringRemain, 1, dl.DateLocation + 7),
StringRemain = SUBSTRING(rs.StringRemain, dl.DateLocation + 8, 8000)
FROM
cte_rSplit rs
CROSS APPLY ( VALUES(ISNULL(NULLIF(PATINDEX('%[0-9][0-9].[0-9][0-9].[0-9][0-9]%', STUFF(rs.StringRemain, 1, 8, '')), 0), 8000)) ) dl (DateLocation)
WHERE
rs.StringRemain LIKE '%[0-9][0-9].[0-9][0-9].[0-9][0-9]%'
)
SELECT
rs.LineNum,
[Date] = CONVERT(DATE, LEFT(rs.ParsedString, 8), 4),
TextValue = SUBSTRING(rs.ParsedString, 9, 8000)
FROM
cte_rSplit rs;
GO
IF OBJECT_ID('tempdb..#LegacyInfo', 'U') IS NOT NULL
DROP TABLE #LegacyInfo;
CREATE TABLE #LegacyInfo (
id INT NOT NULL IDENTITY(1, 1),
TextData VARCHAR(8000) NOT NULL
);
INSERT #LegacyInfo (TextData) VALUES
('23.06.17 - As per quote #8918.1. 7m Swing STage to Positon 1.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
06.07.17 - Completion of Swing Stage to Positon 4.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.'),
('23.06.17 - As per quote #8918.1. 7m Swing STage to Positon 1.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
05.07.17 Stripped and rebuilt boat ready for positon 4 but rained off.
06.07.17 - Completion of Swing Stage to Positon 4.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.
21.07.17 - Built Access Tower to get acess to roof.
Got swing Stage onto roof.
No access to building unable to get parapit clamps and wire up.'),
('31.12.17 - This is just a test...'),
('01.01.17 - Line 1
Some other text following line 1.
22.02.17 - Line 2
More stuff about line 2.');
SELECT
li.id, LineNum, Date, TextValue
FROM
#LegacyInfo li
CROSS APPLY dbo.ParseLegacyInfo(li.TextData);