SQL 标识特定的 CharIndex,然后向后工作以获取字符串的上一部分



不幸的是,我们有一个更改日志将所有更改连接成一个长字符串。

username1 xx:xx:xx
start -> mm/dd/yy
approved no -> yes
username2 xx:xx:xx
firm no -> yes
reqby mm/dd/yy -> mm/dd/yy
target -> mm/dd/yy
etc...

我需要向下跳过字符串,直到找到"目标"更改,然后返回以查找与该更改关联的用户名。 所以在上面的实例中,我会找到"目标",然后回头看,它是由 username2 制作的。

问题在于,在我们找到"目标"更改所在的索引之前,可以进行任意数量的更改。 如果我能像反向循环一样向后退,我就可以查找时间戳'%::%'的第一个实例。

有没有办法使用 case 语句在 SQL 中进行反向循环? 或者是否需要执行存储过程?

例:

daviejo  16:57:39 New Record.
daviejo  17:00:07
 Req. By: 02/12/15 -> 02/17/15
Released: n -> y
scottwi  17:00:19
 Target:  -> 02/12/15
daviejo  17:00:07
 Req. By: 02/17/15 -> 03/17/15
daviejo  17:00:07
 Req. By: 03/17/15 -> 03/30/15
scottwi  13:00:15
 Target:  02/12/15 -> 03/25/15

我想看到斯科特维两次的记录。 我可以解析出日期等。 这将按用户名分组到 ssrs 报告中,其中包含每个更改的详细信息。

一种棘手的方法 - 很大程度上取决于您使用的换行符! - 将是这样的:

DECLARE @s VARCHAR(MAX)=
'username1 xx:xx:xx
start -> mm/dd/yy
approved no -> yes
username2 xx:xx:xx
firm no -> yes
reqby mm/dd/yy -> mm/dd/yy
target -> mm/dd/yy
username5 xx:xx:xx
firm no -> yes
reqby mm/dd/yy -> mm/dd/yy
target -> mm/dd/yy';
DECLARE @AsXml XML=
(
SELECT CAST('<block><item>' 
       + REPLACE
         (
           REPLACE(
                   @s
                  ,CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10)
                  ,'</item></block><block><item>'
                  )
            ,CHAR(13) + CHAR(10)
            ,'</item><item>'
          ) 
       + '</item></block>' AS XML)
);

结果

<block>
  <item>username1 xx:xx:xx</item>
  <item>start -&gt; mm/dd/yy</item>
  <item>approved no -&gt; yes</item>
</block>
<block>
  <item>username2 xx:xx:xx</item>
  <item>firm no -&gt; yes</item>
  <item>reqby mm/dd/yy -&gt; mm/dd/yy</item>
  <item>target -&gt; mm/dd/yy</item>
</block>
<block>
  <item>username5 xx:xx:xx</item>
  <item>firm no -&gt; yes</item>
  <item>reqby mm/dd/yy -&gt; mm/dd/yy</item>
  <item>target -&gt; mm/dd/yy</item>
</block>

您像这样查询 XML

SELECT Item.value('.','varchar(max)') AS item
      ,Item.value('../item[1]','varchar(max)') AS RelatedUser
FROM @AsXml.nodes('/block/item') AS One(Item)
WHERE Item.value('.','varchar(max)') LIKE 'target%'

你得到

item                RelatedUser
target -> mm/dd/yy  username2 xx:xx:xx
target -> mm/dd/yy  username5 xx:xx:xx

使用编辑中的示例数据进行测试。有了这个,你得到(注意"目标"前面的空间!

item                              RelatedUser
Target:  -> 02/12/15              scottwi  17:00:19
Target:  02/12/15 -> 03/25/15     scottwi  13:00:15

最新更新