从字符串中提取两个日期值
Extract two date values from a string
我想从字符串中提取两个日期值。
我可以部分完成。
请注意,日期将放置在字符串中的任何位置。
DECLARE @Stringval VARCHAR(500);
SET @Stringval = '2012-05-23 - hdfDice - somewhere - 5-23-12 Alpha';
IF ISDATE(SUBSTRING(@Stringval, patindex('%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', @Stringval), 10)) = 1
BEGIN
-- Shows first date of 2012-05-23 fine. Works!
PRINT SUBSTRING(@Stringval, patindex('%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', @Stringval), 10);
END
IF ISDATE(SUBSTRING(@Stringval, patindex('%[0-9]-[0-9][0-9]-[0-9][0-9]%', @Stringval), 7)) = 1
BEGIN
-- DOES NOT EXTRACT THE SECOND DATE PROPERLY OF 5-23-12. It shows as 2-05-23
PRINT SUBSTRING(@Stringval, patindex('%[0-9]-[0-9][0-9]-[0-9][0-9]%', @Stringval), 7);
END
首先,作为在您以后的问题中要考虑的注释,您已经很好地发布了您的代码,但是您本可以发布一些更全面的示例数据 - 我们只有一个示例可以使用,所以错误的可能性很大。
下面是示例数据的更好示例:
DECLARE @Strings As TABLE
(
Id int identity(1,1),
StringVal VARCHAR(500)
);
INSERT INTO @Strings (StringVal) VALUES
-- Both dates are valid
('2012-05-23 - hdfDice - somewhere - 5-23-12 Alpha'),
(' 5-23-12 - hdfDice - somewhere - 2012-05-23 Alpha'),
('5-23-12 - hdfDice - somewhere - 2012-05-23 Alpha'),
('15-23-12 - hdfDice - somewhere - 2012-05-23 Alpha'),
-- One date is invalid
('5-53-12 - hdfDice - somewhere - 2012-05-23 Alpha'),
('13-23-12 - hdfDice - somewhere - 2012-05-23 Alpha'),
('5-23-12 - hdfDice - somewhere - 2012-05-33 Alpha'),
('5-23-12 - hdfDice - somewhere - 2012-15-23 Alpha'),
('5-23-12 - hdfDice - somewhere - 2012-1x-23 Alpha'),
('y-23-12 - hdfDice - somewhere - 2012-05-23 Alpha'),
-- both dates are invalid
('5-43-12 - hdfDice - somewhere - 2012-1x-23 Alpha'),
('y-23-12 - hdfDice - somewhere - 2012-15-23 Alpha');
由于您试图提取两种不同的格式,因此您还需要不同的样式来将不同的字符串表示形式转换为正确的日期。此外,第二种字符串格式有点问题,因为它可能以一位或两位数字开头(注意:我假设其他部分将始终包含两位数字 - 假设您需要验证是否要使用我的建议的解决方案) - 所以我使用了两种不同的模式来找到它 - 一个有两个数字,另一个有 space 和一个数字。
下一步是验证第二个日期模式是否与第一个日期模式匹配(因为这是您首先遇到的问题)- 所以我在开头添加了 [^0-9]
使用两位数字的模式。
因为现在我正在使用三种不同的模式和两种不同的长度和样式,所以我决定将该数据存储在 table 变量中 - 如下所示:
DECLARE @Dates AS TABLE
(
Pattern varchar(100),
Length int,
ConvertStyle int
)
INSERT INTO @Dates (Pattern, Length, ConvertStyle) VALUES
('% [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', 11, 120),
('%[^0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', 8, 10),
('% [0-9]-[0-9][0-9]-[0-9][0-9]%', 8, 10);
现在我所要做的就是 cross join
字符串 table 到日期 table,并使用几个 cross apply
进行计算,我想出了以下查询:
SELECT Id
, Stringval
, DateIndex
, DateString
, DateValue
FROM @Strings
CROSS JOIN @Dates
CROSS APPLY (SELECT PATINDEX(Pattern, ' '+ Stringval) As DateIndex) As foundIndex
CROSS APPLY (SELECT IIF(DateIndex > 0, SUBSTRING(' '+ Stringval, DateIndex + 1, Length), NULL) As DateString) As extractedStrings
CROSS APPLY (SELECT TRY_CONVERT(Date, DateString, ConvertStyle) As DateValue) As extractedDates
WHERE DateValue IS NOT NULL
ORDER BY Id, DateIndex
结果:
Id Stringval DateIndex DateString DateValue
1 2012-05-23 - hdfDice - somewhere - 5-23-12 Alpha 1 2012-05-23 2012-05-23
1 2012-05-23 - hdfDice - somewhere - 5-23-12 Alpha 36 5-23-12 2012-05-23
2 5-23-12 - hdfDice - somewhere - 2012-05-23 Alpha 2 5-23-12 2012-05-23
2 5-23-12 - hdfDice - somewhere - 2012-05-23 Alpha 34 2012-05-23 2012-05-23
3 5-23-12 - hdfDice - somewhere - 2012-05-23 Alpha 1 5-23-12 2012-05-23
3 5-23-12 - hdfDice - somewhere - 2012-05-23 Alpha 33 2012-05-23 2012-05-23
4 15-23-12 - hdfDice - somewhere - 2012-05-23 Alpha 34 2012-05-23 2012-05-23
5 5-53-12 - hdfDice - somewhere - 2012-05-23 Alpha 33 2012-05-23 2012-05-23
6 13-23-12 - hdfDice - somewhere - 2012-05-23 Alpha 34 2012-05-23 2012-05-23
7 5-23-12 - hdfDice - somewhere - 2012-05-33 Alpha 1 5-23-12 2012-05-23
8 5-23-12 - hdfDice - somewhere - 2012-15-23 Alpha 1 5-23-12 2012-05-23
9 5-23-12 - hdfDice - somewhere - 2012-1x-23 Alpha 1 5-23-12 2012-05-23
10 y-23-12 - hdfDice - somewhere - 2012-05-23 Alpha 33 2012-05-23 2012-05-23
您可以在 Rextester
上观看现场演示
我想从字符串中提取两个日期值。
我可以部分完成。
请注意,日期将放置在字符串中的任何位置。
DECLARE @Stringval VARCHAR(500);
SET @Stringval = '2012-05-23 - hdfDice - somewhere - 5-23-12 Alpha';
IF ISDATE(SUBSTRING(@Stringval, patindex('%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', @Stringval), 10)) = 1
BEGIN
-- Shows first date of 2012-05-23 fine. Works!
PRINT SUBSTRING(@Stringval, patindex('%[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', @Stringval), 10);
END
IF ISDATE(SUBSTRING(@Stringval, patindex('%[0-9]-[0-9][0-9]-[0-9][0-9]%', @Stringval), 7)) = 1
BEGIN
-- DOES NOT EXTRACT THE SECOND DATE PROPERLY OF 5-23-12. It shows as 2-05-23
PRINT SUBSTRING(@Stringval, patindex('%[0-9]-[0-9][0-9]-[0-9][0-9]%', @Stringval), 7);
END
首先,作为在您以后的问题中要考虑的注释,您已经很好地发布了您的代码,但是您本可以发布一些更全面的示例数据 - 我们只有一个示例可以使用,所以错误的可能性很大。
下面是示例数据的更好示例:
DECLARE @Strings As TABLE
(
Id int identity(1,1),
StringVal VARCHAR(500)
);
INSERT INTO @Strings (StringVal) VALUES
-- Both dates are valid
('2012-05-23 - hdfDice - somewhere - 5-23-12 Alpha'),
(' 5-23-12 - hdfDice - somewhere - 2012-05-23 Alpha'),
('5-23-12 - hdfDice - somewhere - 2012-05-23 Alpha'),
('15-23-12 - hdfDice - somewhere - 2012-05-23 Alpha'),
-- One date is invalid
('5-53-12 - hdfDice - somewhere - 2012-05-23 Alpha'),
('13-23-12 - hdfDice - somewhere - 2012-05-23 Alpha'),
('5-23-12 - hdfDice - somewhere - 2012-05-33 Alpha'),
('5-23-12 - hdfDice - somewhere - 2012-15-23 Alpha'),
('5-23-12 - hdfDice - somewhere - 2012-1x-23 Alpha'),
('y-23-12 - hdfDice - somewhere - 2012-05-23 Alpha'),
-- both dates are invalid
('5-43-12 - hdfDice - somewhere - 2012-1x-23 Alpha'),
('y-23-12 - hdfDice - somewhere - 2012-15-23 Alpha');
由于您试图提取两种不同的格式,因此您还需要不同的样式来将不同的字符串表示形式转换为正确的日期。此外,第二种字符串格式有点问题,因为它可能以一位或两位数字开头(注意:我假设其他部分将始终包含两位数字 - 假设您需要验证是否要使用我的建议的解决方案) - 所以我使用了两种不同的模式来找到它 - 一个有两个数字,另一个有 space 和一个数字。
下一步是验证第二个日期模式是否与第一个日期模式匹配(因为这是您首先遇到的问题)- 所以我在开头添加了 [^0-9]
使用两位数字的模式。
因为现在我正在使用三种不同的模式和两种不同的长度和样式,所以我决定将该数据存储在 table 变量中 - 如下所示:
DECLARE @Dates AS TABLE
(
Pattern varchar(100),
Length int,
ConvertStyle int
)
INSERT INTO @Dates (Pattern, Length, ConvertStyle) VALUES
('% [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', 11, 120),
('%[^0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', 8, 10),
('% [0-9]-[0-9][0-9]-[0-9][0-9]%', 8, 10);
现在我所要做的就是 cross join
字符串 table 到日期 table,并使用几个 cross apply
进行计算,我想出了以下查询:
SELECT Id
, Stringval
, DateIndex
, DateString
, DateValue
FROM @Strings
CROSS JOIN @Dates
CROSS APPLY (SELECT PATINDEX(Pattern, ' '+ Stringval) As DateIndex) As foundIndex
CROSS APPLY (SELECT IIF(DateIndex > 0, SUBSTRING(' '+ Stringval, DateIndex + 1, Length), NULL) As DateString) As extractedStrings
CROSS APPLY (SELECT TRY_CONVERT(Date, DateString, ConvertStyle) As DateValue) As extractedDates
WHERE DateValue IS NOT NULL
ORDER BY Id, DateIndex
结果:
Id Stringval DateIndex DateString DateValue
1 2012-05-23 - hdfDice - somewhere - 5-23-12 Alpha 1 2012-05-23 2012-05-23
1 2012-05-23 - hdfDice - somewhere - 5-23-12 Alpha 36 5-23-12 2012-05-23
2 5-23-12 - hdfDice - somewhere - 2012-05-23 Alpha 2 5-23-12 2012-05-23
2 5-23-12 - hdfDice - somewhere - 2012-05-23 Alpha 34 2012-05-23 2012-05-23
3 5-23-12 - hdfDice - somewhere - 2012-05-23 Alpha 1 5-23-12 2012-05-23
3 5-23-12 - hdfDice - somewhere - 2012-05-23 Alpha 33 2012-05-23 2012-05-23
4 15-23-12 - hdfDice - somewhere - 2012-05-23 Alpha 34 2012-05-23 2012-05-23
5 5-53-12 - hdfDice - somewhere - 2012-05-23 Alpha 33 2012-05-23 2012-05-23
6 13-23-12 - hdfDice - somewhere - 2012-05-23 Alpha 34 2012-05-23 2012-05-23
7 5-23-12 - hdfDice - somewhere - 2012-05-33 Alpha 1 5-23-12 2012-05-23
8 5-23-12 - hdfDice - somewhere - 2012-15-23 Alpha 1 5-23-12 2012-05-23
9 5-23-12 - hdfDice - somewhere - 2012-1x-23 Alpha 1 5-23-12 2012-05-23
10 y-23-12 - hdfDice - somewhere - 2012-05-23 Alpha 33 2012-05-23 2012-05-23
您可以在 Rextester
上观看现场演示