2012-02-10 48 views
7

đầu vào mẫu:Làm thế nào để loại bỏ bất kỳ số trailing từ một chuỗi?

"Hi there how are you"

"? Pizza nơi # 1 ở New York là gì"

"Dominoes là số 1"

"Blah blah 123.123"

"More blah 12.321 123.123 123.132"

Dự kiến ​​sản lượng:

"Hi there thế nào bạn "

" Địa điểm pizza số 1 ở NYC là gì? "

"Dominoes là số"

"Blah blah"

"More blah"

Tôi nghĩ nó là một quá trình 2 bước:

  1. Chia toàn bộ chuỗi ký tự, một hàng cho mỗi ký tự (bao gồm dấu cách), trong đảo ngược đặt hàng
  2. Lặp lại, và cho mỗi một nếu đó là một không gian hoặc một số, bỏ qua, nếu không thêm vào bắt đầu của một mảng khác.

Và tôi sẽ kết thúc với kết quả mong muốn.

Tôi có thể nghĩ ra một vài cách nhanh chóng và bẩn thỉu, nhưng điều này cần phải thực hiện khá tốt, vì nó là một trình kích hoạt chạy trên một bảng bận, vì vậy tôi nghĩ sẽ ném nó ra cho các chuyên gia T-SQL.

Mọi đề xuất?

+1

tôi đang làm việc trên một cái gì đó một chút hiệu quả hơn so với phác thảo trong hai bước proc của bạn ess, chỉ cần cho tôi một vài phút. – zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

+0

@zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz - tôi chờ đợi với hơi thở bướng bỉnh. :) – RPM1984

+0

Hãy cho tôi biết suy nghĩ của bạn. – zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

Trả lời

4

Giải pháp này nên hiệu quả hơn một chút vì trước tiên nó kiểm tra xem chuỗi có chứa số hay không, sau đó nó kiểm tra để xem nếu chuỗi kết thúc bằng một số.

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 

Nếu bạn chạy

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

Nó sẽ trở lại

'More blah' 
+0

Tôi đã thử nghiệm điều này trên cơ sở dữ liệu SQL Server 2008 với 30.000 hàng và mất <1 giây. – zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

+0

Các vòng lặp chậm trong SQL và Isnumeric() không làm những gì bạn nghĩ. thử SELECT ISNUMERIC ('.'), ISNUMERIC ('$'), ISNUMERIC ('1e7') và nhiều mục khác trả về true khi nó không chỉ là chữ số. – Davos

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)) 

LƯU Ý: Tôi đã bao gồm dấu gạch ngang trong kết hợp regex hợp lệ.

+0

Sẽ không hiệu quả hơn khi kiểm tra xem liệu một ký tự có phải là số thay vì không phải là một chữ cái không? Có lẽ không phải là một sự khác biệt hiệu suất rất lớn mặc dù. – zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

+0

yep. chắc chắn. tôi hoàn toàn quên từ khóa 'IsNumeric'. –

3

Vòng lặp trên bàn bận sẽ rất khó thực hiện đầy đủ. Sử dụng REVERSE và PATINDEX để tìm số không đầu tiên, bắt đầu một SUBSTRING ở đó, sau đó REVERSE kết quả. Điều này sẽ rất chậm mà không có vòng lặp.

Ví dụ của bạn ngụ ý rằng bạn cũng không muốn khớp không gian.

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 

câu trả lời cuối cùng: ngược (substring (đảo ngược (@s), patindex ('% [^ 0-9]%', đảo ngược (@s)), 1 + len (@s) - patindex ('% [^ 0-9]%', đảo ngược (@s))))

+2

Đây là gợi ý tốt nhưng bạn có thể làm cho nó ngắn hơn một chút. 'substring (s, 1, 1 + len (s) - patindex ('% [^ 0-9]%', đảo ngược (s)))' –

+0

Điều đó chắc chắn tốt hơn. – bsdfm

-1

Cảm ơn tất cả những đóng góp đó là rất hữu ích. Để đi xa hơn và giải nén ra JUST số dấu:

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

tôi cần phải sắp xếp vào hậu tố số nên phải hạn chế mô hình để numerics và để có được xung quanh con số có độ dài khác nhau sắp xếp dưới dạng văn bản (ví dụ: tôi muốn 2 để sắp xếp trước 19) đúc kết quả:

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

Đây phải là nhận xét chứ không phải là câu trả lời. Kiểm tra [câu hỏi metaSO] này (http://meta.stackexchange.com/questions/7656/how-do-i-write-a-good-answer-to-a-question) và [Jon Skeet: Blog mã hóa] (http://msmvps.com/blogs/jon_skeet/archive/2009/02/17/answering-technical-questions-helpfully.aspx) về cách đưa ra câu trả lời đúng. – Yaroslav

3

tôi tin rằng các truy vấn dưới đây là nhanh chóng và hữu ích

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

Không hoạt động đối với các đầu vào mẫu được cung cấp trong OP –

Các vấn đề liên quan