2014-02-12 102 views
1

我有一個查詢(sql-server),我試圖從字符串中提取信息。
該表有3個字段(Key1 =訂單號,datestamp =僅日期,logtext =字符串)。查找SQL字符串中的信息

我想要的是key1,datestamp和來自字符串的信息。我需要一些數據,包括「銷售代表:」(例如:「銷售代表:DSCANTL1 - > BDENNIK1」)。我在查詢中顯示的「salesreps」列中有我需要的內容,但是如果在logtext列中出現多個「Sales Reps」的情況,我還想顯示其中的每一個。 我還希望在「銷售代表:」之前出現第一個時間戳(##:##:##),並且還要在該時間戳之前的代表名稱。
正如我的數據中所提供的,有時在「銷售代表:」有時沒有時間戳,有時候是有的。

下面是表格中數據的一個例子。

Key1 datestamp    logtext 
337316 2013-01-15 00:00:00.000 JWebb 10:41:19 Sales Reps: ARCHITE1 -> BDENNIK1 
338644 2013-01-28 00:00:00.000 TWert 10:21:26 Sales Reps: PHEISSE1 -> PHEISSE2 
305699 2013-08-23 00:00:00.000 JDickey 11:24:27 Status: no -> yesJDickey 11:25:03 SalesReps: -> NOREP JDickey 11:25:08 Status: yes -> no 
360429 2014-02-10 00:00:00.000 TThomas 15:51:01 Need By: 02/20/14 -> 02/14/14 Ship By: 02/20/14 -> 02/14/14 BOatman 15:53:27 Sales Reps: TCONNOR1 -> TCONNOR1~DSIDES1 
347094 2013-07-12 00:00:00.000 LLilley 10:58:07 Amount: 864 -> 876.5 Order Amount: 864 -> 876.5 LLilley 10:58:08 Total Number Releases: 2 -> 3 Total Number Releases: 3 -> 4 Sales Reps: BBARBER -> LDODGE1 
337319 2013-01-15 00:00:00.000 JWebb 10:25:20 Sales Reps: ARCHITE1 -> BDENNIK1 Sales Reps: BDENNIK1 -> ARCHITE1 338524 2013-01-28 00:00:00.000 TLong 12:01:54 Sales Reps: DESIGNM1-> SPARTAN1 LLilley 11:59:07 Sales Reps: SPARTAN1 -> TKELLEY1 

以下是我已經爲我的查詢:

已更新2014年2月14日:

;WITH cteChanges as 
(
select  Key1, DateStamp 
      ,logtext 
      ,Substring(logtext,PATINDEX('%Sales Reps:%',logtext),35) salesreps 
      ,Substring(logtext,PATINDEX('%New Record%',logtext),10) newOrNot 
      ,(len(logtext) - len(replace(logtext,'Sales Reps:','')))/LEN('Sales Reps:') cnt 
      ,REVERSE(SUBSTRING(REVERSE(substring(REPLACE(Logtext, CHAR(10), '|'),0,PATINDEX('%Sales Reps:%',logtext))) 
        ,CHARINDEX('|',REVERSE(substring(REPLACE(Logtext, CHAR(10), '|'),0,PATINDEX('%Sales Reps:%',logtext)+1))),8)) ChangeTime 
      ,SUBSTRING(REVERSE(LEFT(REVERSE(substring(REPLACE(Logtext, CHAR(10), '|'),0,PATINDEX('%Sales Reps:%',logtext))) 
        ,CHARINDEX('||',REVERSE(substring(REPLACE(Logtext, CHAR(10), '|'),0,PATINDEX('%Sales Reps:%',logtext))))-1)),0,10) ChangePerson 

FROM  chglog (nolock) 

WHERE  identifier = 'OrderHed' and company ='EII' and tablename = 'OrderHed' 
      and Logtext like '%Sales Reps:%' 
      and Datestamp >= '01/01/2013' 
      and rtrim(Left(LogText,9)) <> 'manager' 

      --and Substring(logtext,PATINDEX('%New Record%',logtext),10) <> 'New Record' 
) 

SELECT  Key1 OrderNum 
      ,DateStamp 
      --,logtext 
      ,SUBSTRING(salesreps,1,PATINDEX('%-%',salesreps)) + Substring(salesreps,PATINDEX('%>%',salesreps) 
        ,CASE WHEN (convert(int,charINDEX(char(10),Substring(salesreps,PATINDEX('%>%',salesreps),10))-1)) < 0 THEN 10 ELSE 
        (charINDEX(char(10),Substring(salesreps,PATINDEX('%>%',salesreps),10))-1) END) salesreps 
      ,ChangePerson 
      ,ChangeTime 
      ,cnt TimesSalesPersonChanged 
      --,newOrNot 

FROM  cteChanges 

ORDER BY DateStamp, Key1 
+1

這種規模的字符串操作會更適合CLR 。 – 2014-02-12 18:44:04

+0

有沒有其他想法? – Kevin

+0

「logtext」字段中的文本是否有製表符?例如,在最後一條記錄 - 「... ARCHITE1 338524 2013-01-28 ...」中,時間戳之前的長空間實際上是作爲選項卡存儲在數據庫中的嗎? – Ruslan

回答

0

我能修改您的查詢,使其返回銷售代表條目作爲單獨的行(至少那些以時間戳爲前綴的行)。

這應該把你放在正確的軌道上。我的調試能力是有限的,因爲我沒有原始數據(或模式),但它應該可以解決您最初在CTE看到第一個「銷售代表」條目時遇到的問題。

爲了得到這個運行,您首先需要創建這個函數:

create function dbo.SplitString 
    (
     @str nvarchar(4000), 
     @separator char(1) 
    ) 
    returns table 
    AS 
    return (
     with tokens(p, a, b) AS (
      select 
       1, 
       1, 
       charindex(@separator, @str) 
      union all 
      select 
       p + 1, 
       b + 1, 
       charindex(@separator, @str, b + 1) 
      from tokens 
      where b > 0 
     ) 
     select 
      p-1 zeroBasedOccurance, 
      substring(
       @str, 
       a, 
       case when b > 0 then b-a ELSE 4000 end) 
      AS s 
     from tokens 
    ) 
    GO 

那麼,這是你查詢的新版本(我註釋掉&刪除一些你有原創的東西這裏是因爲某些列丟失,其中一些列丟失了錯誤,但這很可能是因爲我的測試模式存在差異)。

;WITH cteChanges as 
(
select  l.Key1, l.DateStamp 
      ,l.logtext 
      ,Substring(m.S,PATINDEX('%Sales Reps:%',m.S),35) salesreps 
      ,Substring(m.S,PATINDEX('%New Record%',m.S),10) newOrNot 
      ,(len(m.S) - len(replace(m.S,'Sales Reps:','')))/LEN('Sales Reps:') cnt 
      ,REVERSE(SUBSTRING(REVERSE(substring(REPLACE(m.S, CHAR(10), '|'),0,PATINDEX('%Sales Reps:%',m.S))) 
        ,CHARINDEX('|',REVERSE(substring(REPLACE(m.S, CHAR(10), '|'),0,PATINDEX('%Sales Reps:%',m.S)+1))),8)) ChangeTime 
      ,SUBSTRING(REVERSE(LEFT(REVERSE(substring(REPLACE(m.S, CHAR(10), '|'),0,PATINDEX('%Sales Reps:%',m.S))) 
        ,CHARINDEX('||',REVERSE(substring(REPLACE(m.S, CHAR(10), '|'),0,PATINDEX('%Sales Reps:%',m.S))))-1)),0,10) ChangePerson 

FROM  chglog (nolock) l 
    cross apply dbo.SplitString(replace(l.logtext, char(13), ''), char(10)) m 
WHERE  m.S like '%Sales Reps:%' 

      --and Substring(logtext,PATINDEX('%New Record%',logtext),10) <> 'New Record' 
) 

SELECT  Key1 OrderNum 
      ,DateStamp 
      ,logtext 
      ,SUBSTRING(salesreps,1,PATINDEX('%-%',salesreps)) + Substring(salesreps,PATINDEX('%>%',salesreps) 
        ,CASE WHEN (convert(int,charINDEX(char(10),Substring(salesreps,PATINDEX('%>%',salesreps),10))-1)) < 0 THEN 10 ELSE 
        (charINDEX(char(10),Substring(salesreps,PATINDEX('%>%',salesreps),10))-1) END) salesreps 
      --,ChangePerson 
      --,ChangeTime 
      --,cnt TimesSalesPersonChanged 
      --,newOrNot 

FROM  cteChanges 

ORDER BY DateStamp, Key1 

我的主要變化是添加CROSS APPLY子句中有分割字符串分解成線路終端不同的行。

查看完整SQLFiddle這裏:http://sqlfiddle.com/#!3/f8a67/11

而且,在這裏看到我原來嘗試做不同的方式(可能是更容易?):http://sqlfiddle.com/#!6/a5940/3