【问题标题】:SQL server 2008 patindex recursionSQL Server 2008 patindex 递归
【发布时间】:2017-02-02 04:40:37
【问题描述】:

我想找到一个表达式的最新实例,然后继续寻找更好的匹配,然后选择最佳匹配。

我正在查看的单元格是一个重复附加的日志,带有注释,后跟用户名和时间戳。

示例单元格内容:

Starting the investigation.
JWAYNE entered the notes above on 08/12/1976 12:01

Taking over the case. Not a lot of progress recently.
CEASTWOOD entered the notes above on 03/14/2001 09:04

No wonder this case is not progressing, the whole town is covering up some shenanigans!
CEASTWOOD entered the notes above on 03/21/2001 05:23

Star command was right, this investigation has been tossed around like a hot potato for a long time!
BLIGHTYEAR entered the notes above on 08/29/2659 08:01

我不是数据库范式规则方面的专家,但很烦人的是条目被挤在一个单元格中,这使得我的工作是隔离和检查特定单词的注释,尤其是当单元格重复多行时,直到调查结束,将来自未来阶段的注释放入过去事件的注释列中,最重要的是时间戳使时间戳 PATINDEX 甚至几分钟的余量都不可靠,如下所示:

CaseID, Username,  Notes,             Phase, Timestamp
E18902, JWAYNE,    Starting....08:01, E1,    03/14/2001 09:13
E18902, CEASTWOOD, Starting....08:01, E2,    03/14/2001 09:13
E18902, CEASTWOOD, Starting....08:01, E3,    03/21/2001 05:34
E18902, BLIGHTYEAR,Starting....08:01, E4,    08/29/2659 07:58

现在我正在对整个字符串进行反向操作,然后使用 patindex 查找用户名,然后进行子字符串化以仅选择该调查阶段的注释,问题是当同一个用户输入多个阶段的注释时,我的简单“寻找第一个盯着字符串末尾移动到顶部的匹配项”选择了错误的条目。我的第一个想法是搜索用户名,然后再次检查以查看更远的条目是否更好匹配(注意时间戳与列时间戳),但我不知道如何编码......

我必须进行复杂的字符串拆分还是有更简单的解决方案?

【问题讨论】:

  • 这听起来可能比在查询中使用执行字符串操作的过程语言处理得更好。您查询的最终目的地是什么?能不能涉及到C#这样的高级语言?
  • 另外,你如何确定“更好的匹配”?
  • 一个更好的匹配会进一步增加字符串并找到同一用户的另一个注释,但时间戳列时间更接近注释条目末尾列出的时间戳。基本上我现在遇到的问题是我当前的解决方案是在它检测到的用户名的第一个实例中放弃,我希望能够比较检测并评估每个实例,并根据时间戳的接近程度选择最好的一个。最终用途是 SSRS 报告,那里有 VB/C 解决方案的一些选项吗?
  • 如您所见,单元格内容是否包括换行符/回车符?
  • 不幸的是,大多数是一个或多个 char(10),有些是 char(13) 和 char(10)。我发现每个字符 10 和 13 都有一个嵌套的 REPLACE。

标签: sql sql-server sql-server-2008 recursion patindex


【解决方案1】:

这是我的建议。这是一个记录,但如果您愿意,可以将其转换为用户定义的表值函数。

我将使用您上面的示例数据。

 declare @sourceText nvarchar(max)
    ,    @workText   nvarchar(max)
    ,    @xml        xml

 set @sourceText = <your example text in your question>
 set @workText = @sourceText

 -- We're going to replace all the carriage returns and line feeds with 
 -- characters unlikely to appear in your text.  (If they are, use some
 -- other character.)

 set    @workText = REPLACE(@workText, char(10), '|')
 set    @workText = REPLACE(@workText, char(13), '|')

 -- Now, we're going to turn your text into XML.  Our first target is 
 -- the string of four "|" characters that the blank lines between entries
 -- will be turned into.  (If you've got 3, or 6, or blanks in between, 
 -- adjust accordingly.)

set @workText = REPLACE(@workText, '||||', '</line></entry><entry><line>')

-- Now we replace every other "|".  
set @workText = REPLACE(@workText, '|', '</line><line>')

-- Now we construct the rest of the XML and convert the variable to an 
-- actual XML variable.
set @workText = '<entry><line>' + @workText + '</line></entry>'
set @workText = REPLACE(@workText, '<line></line>','') -- Get rid of any empty nodes.

set @xml = CONVERT(xml, @workText)

我们现在应该有一个如下所示的 XML 片段。 (此时将select @xml插入SQL即可看到。)

开始调查。JWAYNE 于 08/12/1976 12:01 输入上述注释接手此案。最近进展不大。CEASTWOOD 于 03/14/2001 09:04 输入上述注释难怪这案子没有进展,全镇都在掩盖一些恶作剧!CEASTWOOD 于 03/21/2001 05:23 输入上述注释星令说得对,这次调查像烫手山芋一样折腾了半天!BLIGHTYEAR 于 08/29/2659 08:01 输入上述注释 我们现在可以将此 XML 转换为我们更喜欢的 XML:
  set @xml = @xml.query(
  'for $entry in /entry
    return <entry><data>
    {
    for $line in $entry/line[position() < last()] 
    return string($line)
    }
    </data>
    <timestamp>{ data($entry/line[last()]) }</timestamp>     
 </entry>
 ')

这为我们提供了如下所示的 XML(出于长度原因,仅显示了一个条目):

开始调查。JWAYNE 于 08/12/1976 12:01 输入上述注释

您可以使用此查询将其转换回表格数据:

选择 EntryData = R.lines.value('data[1]', 'nvarchar(max)') , EntryTimestamp = R.lines.value('timestamp[1]', 'nvarchar(MAX)') 从 @xml.nodes('/entry') 作为 R(lines)

...并获取如下所示的数据。

从那里,您可以做任何您需要做的事情。

【讨论】:

  • 这是否适用于多行注释条目?大多数实际数据由用户名页脚前的一行或多行注释组成。
  • 是的,应该。转换中的return string($line) 应该将除最后一个之外的所有&lt;line&gt; 元素合并为一个&lt;data&gt; 标记。
  • 这对于我随问题提交的示例数据非常有效!我现在遇到时间戳之间换行数不一致的情况。
  • 是的,我知道这会是个问题!我的解决方案确实假设有一种可靠、一致的方式来判断一个条目已停止而另一个条目已开始。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-17
相关资源
最近更新 更多