2012-02-10 80 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

相关问题