TSQL:查找字符串中具有不同字符的日期

TSQL:查找字符串中具有不同字符的日期,sql,sql-server,tsql,sql-server-2016,Sql,Sql Server,Tsql,Sql Server 2016,我需要在列名Filename的字符串中查找连续日期。字符串中有其他带有破折号或其他字符(如下划线)的数字,但我只需要连续数字 需要从文件名中提取日期。我知道数据只是哇,多个供应商,多个文件命名格式是原因 这个问题与这个问题类似,但它寻找的是不同的需求: 预期结果: 实际结果: 测试代码: 试着这样做: DROP TABLE #StuID GO CREATE TABLE #StuID ( FILENAME VARCHAR(MAX) ,StudentID INT ) INSERT INTO #S

我需要在列名Filename的字符串中查找连续日期。字符串中有其他带有破折号或其他字符(如下划线)的数字,但我只需要连续数字

需要从文件名中提取日期。我知道数据只是哇,多个供应商,多个文件命名格式是原因

这个问题与这个问题类似,但它寻找的是不同的需求:

预期结果:

实际结果:

测试代码:

试着这样做:

DROP TABLE #StuID
GO
CREATE TABLE #StuID (
 FILENAME VARCHAR(MAX)
,StudentID INT
)

INSERT INTO #StuID
( FILENAME  )
VALUES
 ('Smith John D, 11-23-1980, 1234567.pdf')
,('Doe Jane, _01_22_1980_123456.pdf')
,('John Doe, 567891.pdf' );

WITH Casted([FileName],ToXml) AS
(
    SELECT [FILENAME] 
          ,CAST('<x>' + REPLACE(REPLACE(REPLACE(REPLACE(REPLACE([FILENAME],'.',' '),'-',' '),'_',' '),',',' '),' ','</x><x>') + '</x>' AS XML)
    FROM #StuID
)
SELECT [FileName] 
      ,numberFragments.value('/x[.>=1 and .<=31][1]','int') AS MonthFragment --using <=12 might bring back the second fragment twice...
      ,numberFragments.value('/x[.>=1 and .<=31][2]','int') AS DayFragment
      ,numberFragments.value('/x[.>=1960 and .<=2050][1]','int') AS YearFragment
      ,numberFragments.value('/x[.>=100000 and .<=10000000][1]','int') AS StudId
FROM Casted
CROSS APPLY (SELECT ToXml.query('/x[not(empty(. cast as xs:int?))]')) A(numberFragments);
简而言之:

与前面的回答一样,我们将把字符串分解为XML,并过滤可转换为int的片段。 XQuery筛选的神奇之处在于:

我们选择1到31之间的第一个片段,这是一个月 我们选择1到31之间的第二个片段,这是希望的一天 我们选择了1960年到2050年之间的第一个片段,这是充满希望的一年 我们选择学生的id,这是100000到10000000之间的第一个片段。 提示:使用看起来是个不错的主意,可以这样尝试:

DROP TABLE #StuID
GO
CREATE TABLE #StuID (
 FILENAME VARCHAR(MAX)
,StudentID INT
)

INSERT INTO #StuID
( FILENAME  )
VALUES
 ('Smith John D, 11-23-1980, 1234567.pdf')
,('Doe Jane, _01_22_1980_123456.pdf')
,('John Doe, 567891.pdf' );

WITH Casted([FileName],ToXml) AS
(
    SELECT [FILENAME] 
          ,CAST('<x>' + REPLACE(REPLACE(REPLACE(REPLACE(REPLACE([FILENAME],'.',' '),'-',' '),'_',' '),',',' '),' ','</x><x>') + '</x>' AS XML)
    FROM #StuID
)
SELECT [FileName] 
      ,numberFragments.value('/x[.>=1 and .<=31][1]','int') AS MonthFragment --using <=12 might bring back the second fragment twice...
      ,numberFragments.value('/x[.>=1 and .<=31][2]','int') AS DayFragment
      ,numberFragments.value('/x[.>=1960 and .<=2050][1]','int') AS YearFragment
      ,numberFragments.value('/x[.>=100000 and .<=10000000][1]','int') AS StudId
FROM Casted
CROSS APPLY (SELECT ToXml.query('/x[not(empty(. cast as xs:int?))]')) A(numberFragments);
简而言之:

与前面的回答一样,我们将把字符串分解为XML,并过滤可转换为int的片段。 XQuery筛选的神奇之处在于:

我们选择1到31之间的第一个片段,这是一个月 我们选择1到31之间的第二个片段,这是希望的一天 我们选择了1960年到2050年之间的第一个片段,这是充满希望的一年 我们选择学生的id,这是100000到10000000之间的第一个片段。
提示:使用看起来是个不错的主意,我认为您的模式不太正确。此外,还可以使用大小写表达式返回NULL:

在以下情况下,您也可以省去该案例并使用null:


我认为你的模式不太正确。此外,还可以使用大小写表达式返回NULL:

在以下情况下,您也可以省去该案例并使用null:


另一种方法是在使用PATINDEX查找日期后,强制将字符串格式转换为MM/dd/yyyy,然后使用显式样式进行转换:

SELECT *,
       TRY_CONVERT(date,STUFF(STUFF(SUBSTRING(d.FILENAME,V.I, 10),3,1,'/'),6,1,'/'),101)
FROM #dob d
     CROSS APPLY (VALUES(NULLIF(PATINDEX('%[0-9][0-9]_[0-9][0-9]_[0-9][0-9][0-9][0-9]%',d.[FILENAME]),0))) V(I);

另一种方法是在使用PATINDEX查找日期后,强制将字符串格式转换为MM/dd/yyyy,然后使用显式样式进行转换:

SELECT *,
       TRY_CONVERT(date,STUFF(STUFF(SUBSTRING(d.FILENAME,V.I, 10),3,1,'/'),6,1,'/'),101)
FROM #dob d
     CROSS APPLY (VALUES(NULLIF(PATINDEX('%[0-9][0-9]_[0-9][0-9]_[0-9][0-9][0-9][0-9]%',d.[FILENAME]),0))) V(I);

谢谢@Larnu!此解决方案重新设置日期。我感谢你的帮助!谢谢@Larnu!此解决方案重新设置日期。我感谢你的帮助!谢谢你@GordonLinoff。这是一个优雅的解决方案,同样有效。我感谢你的帮助@JM1。这比其他解决方案简单得多。谢谢@GordonLinoff。这是一个优雅的解决方案,同样有效。我感谢你的帮助@JM1。这比其他解决方案简单得多。谢谢@Shnugo!我不知道XQuery。它似乎很强大。除了拆弦之外,你还经常使用它吗?如果是这样,你用它做什么典型的事情?不确定这是否是一个问这个问题的好地方,如果不是,请告诉我哪里是一个好地方。再次感谢。@JM1好吧,不,评论不是详细介绍XQuery:-的最好地方。当您必须处理XMLs时,经常使用这种方法。除此之外,它还允许一些非常有用的黑客攻击,在这些攻击中,您不知何故滥用了XML处理数据的能力。您可能会对它有所感觉…@JM1另一种用法是创建一个未知集,并将其作为XML参数传递给函数或存储过程。在中,我提供了一种将任何SELECT转换为HTML表的方法。一般来说,有人可能会说:这永远是一个黑客,它不会表现得很好,但它允许做一些你可能会说不可能的事情:-谢谢@Shnugo!我不知道XQuery。它似乎很强大。除了拆弦之外,你还经常使用它吗?如果是这样,你用它做什么典型的事情?不确定这是否是一个问这个问题的好地方,如果不是,请告诉我哪里是一个好地方。再次感谢。@JM1好吧,不,评论不是详细介绍XQuery:-的最好地方。当您必须处理XMLs时,经常使用这种方法。除此之外,它还允许一些非常有用的黑客攻击,在这些攻击中,您不知何故滥用了XML处理数据的能力。您可能会对它有所感觉…@JM1另一种用法是创建一个未知集,并将其作为XML参数传递给函数或存储过程。在中,我提供了一种将任何SELECT转换为HTML表的方法。一般来说,有人可能会说:这总是一种黑客行为,它不会表现得很好,但它允许做一些你可能会说不可能的事情:-
SELECT *,
       TRY_CONVERT(date,STUFF(STUFF(SUBSTRING(d.FILENAME,V.I, 10),3,1,'/'),6,1,'/'),101)
FROM #dob d
     CROSS APPLY (VALUES(NULLIF(PATINDEX('%[0-9][0-9]_[0-9][0-9]_[0-9][0-9][0-9][0-9]%',d.[FILENAME]),0))) V(I);