2012-02-10 115 views
7

採樣輸入:如何從字符串中刪除任何尾隨數字?

「你好你怎麼樣」

「?什麼是在紐約市的#1的披薩店」

「多米諾骨牌是1號」

「等等等等123123」

「更多胡說12321 123123 123132」

預期輸出:

「嗨如何你「

」紐約市#1披薩店的位置是什麼?「

「多米諾骨牌是數字」

「等等等等」

「更多嗒嗒」

我想這是一個兩個步驟:

  1. 分割整個字符串轉換成字符,每個字符一行(包括空格),在反轉命令
  2. 循環遍歷,如果是空格或數字,則爲每一個循環,跳過,否則添加到另一個數組的開始

而我最終會得到理想的結果。

我可以想到一些快速和骯髒的方法,但這需要表現得相當好,因爲它是一個在繁忙的表上運行的觸發器,所以我認爲我會把它扔給T-SQL專業人員。

有什麼建議嗎?

+1

我工作的東西多一點效率比在兩步PROC概述ess,給我幾分鐘。 – zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz 2012-02-10 02:28:02

+0

@zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz - 我等着憋氣。 :) – RPM1984 2012-02-10 02:29:12

+0

讓我知道你的想法。 – zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz 2012-02-10 03:07:38

回答

4

該解決方案應該更有效一些,因爲它首先檢查字符串是否包含數字,然後檢查如果字符串以數字結尾。

CREATE FUNCTION dbo.trim_ending_numbers(@columnvalue AS VARCHAR(100)) RETURNS VARCHAR(100) 
    BEGIN 
    --This will make the query more efficient by first checking to see if it contains any numbers at all 
    IF @columnvalue NOT LIKE '%[0-9]%' 
     RETURN @columnvalue 

    DECLARE @counter INT 
    SET @counter = LEN(@columnvalue) 

    IF ISNUMERIC(SUBSTRING(@columnvalue,@counter,1)) = 0 
     RETURN @columnvalue 

    WHILE ISNUMERIC(SUBSTRING(@columnvalue,@counter,1)) = 1 OR SUBSTRING(@columnvalue,@counter,1) = ' ' 
    BEGIN 
     SET @counter = @counter -1 
     IF @counter < 0 
      BREAK 
    END 
    SET @columnvalue = SUBSTRING(@columnvalue,0,@counter+1) 

    RETURN @columnvalue 
    END 

如果運行

SELECT dbo.trim_ending_numbers('More blah 12321 123123 123132') 

它將返回

'More blah' 
+0

我在30,000+行的SQL Server 2008數據庫上測試了這個數據庫,它耗時<1秒。 – zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz 2012-02-10 03:15:44

+0

循環在SQL中很慢,而Isnumeric()不會執行您認爲它的操作。嘗試SELECT ISNUMERIC('。'),ISNUMERIC('$'),ISNUMERIC('1e7')以及更多不僅僅是數字數字而返回true的項目。 – Davos 2015-01-21 23:11:38

0
--DECLARE @String VARCHAR(100) = 'the fat cat sat on the mat' 
--DECLARE @String VARCHAR(100) = 'the fat cat 2 sat33 on4 the mat' 
--DECLARE @String VARCHAR(100) = 'the fat cat sat on the mat1' 
--DECLARE @String VARCHAR(100) = '2121' 
DECLARE @String VARCHAR(100) = 'the fat cat 2 2 2 2 sat on the mat2121' 



DECLARE @Answer NVARCHAR(MAX), 
    @Index INTEGER = LEN(@String), 
    @Character CHAR, 
    @IncorrectCharacterIndex SMALLINT 


-- Start from the end, going to the front. 
WHILE @Index > 0 BEGIN 

    -- Get each character, starting from the end 
    SET @Character = SUBSTRING(@String, @Index, 1) 

    -- Regex check. 
    SET @IncorrectCharacterIndex = PATINDEX('%[A-Za-z-]%', @Character) 

    -- Is there a match? We're lucky here because it will either match on index 1 or not (index 0) 
    IF (@IncorrectCharacterIndex != 0) 
    BEGIN 
     -- We have a legit character. 
     SET @Answer = SUBSTRING(@String, 0, @Index + 1) 
     SET @Index = 0 
    END 
    ELSE 
     SET @Index = @Index - 1 -- No match, lets go back one index slot. 


END 

PRINT LTRIM(RTRIM(@Answer)) 

注意:我在有效的正則表達式匹配中包含短劃線。

+0

測試一個角色是否是一個數字而不是字母是否更有效?雖然可能不是一個巨大的性能差異。 – zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz 2012-02-10 03:08:31

+0

是的。當然。我完全忘了'IsNumeric'關鍵字。 – 2012-02-10 10:10:37

3

忙表上的循環將不太可能充分執行。使用REVERSE和PATINDEX找到第一個非數字,在那裏開始一個SUBSTRING,然後反轉結果。這會很慢,沒有循環。

你的例子暗示你也不想匹配空格。

DECLARE @t TABLE (s NVARCHAR(500)) 
INSERT INTO @t (s) 
VALUES 
('Hi there how are you'),('What is the #1 pizza place in NYC?'),('Dominoes is number 1'),('Blah blah 123123'),('More blah 12321 123123 123132') 

select s 
, reverse(s) as beginning 
, patindex('%[^0-9 ]%',reverse(s)) as progress 
, substring(reverse(s),patindex('%[^0-9 ]%',reverse(s)), 1+len(s)-patindex('%[^0-9 ]%',reverse(s))) as [more progress] 
, reverse(substring(reverse(s),patindex('%[^0-9 ]%',reverse(s)), 1+len(s)-patindex('%[^0-9 ]%',reverse(s)))) as SOLUTION 
from @t 

最終答案: 反向(子(反向(@s),PATINDEX( '%[^ 0-9]%',反向(@s)),1 + LEN(@s) - PATINDEX ('%[^ 0-9]%',反向(@s))))

+2

這是個好建議,但可以縮短一點。 'substring(s,1,1 + len(s) - patindex('%[^ 0-9]%',reverse(s)))' – 2012-02-10 06:53:05

+0

這絕對會更好。 – bsdfm 2012-02-12 22:48:41

-1

感謝所有這些是非常有益的貢獻。更進一步,萃取出JUST尾隨號:

, substring(s, 2 + len(s) - patindex('%[^0-9 ]%',reverse(s)), 99) as numeric_suffix 

我需要排序的編號後綴所以不得不將模式限制爲數字和避開不同長度排序爲文本的數字(即我想2 19前進行排序)把結果:

,cast(substring(s, 2 + len(s) - patindex('%[^0-9]%',reverse(s)),99) as integer) as numeric_suffix 
+0

這應該是一個評論,而不是一個答案。檢查這個[metaSO問題](http://meta.stackexchange.com/questions/7656/how-do-i-write-a-good-answer-to-a-question)和[Jon Skeet:Coding Blog]( http://msmvps.com/blogs/jon_skeet/archive/2009/02/17/answering-technical-questions-helpfully.aspx)如何給出正確的答案。 – Yaroslav 2012-10-11 11:48:05

3

我相信下面的查詢速度快,有用

select reverse(substring(reverse(colA),PATINDEX('%[0-9][a-z]%',reverse(colA))+1, 
len(colA)-PATINDEX('%[0-9][a-z]%',reverse(colA)))) 
from TBLA 
+0

不適用於OP中提供的樣本輸入 – 2016-08-26 15:32:00

相關問題