2010-08-19 27 views
4

我有一個varchar列在我的表之一,如數據:T-SQL查詢來清理VARCHAR列

1234abc 
1234abcde456757 
1234abc Supervisor 
1234abc456 Administrator 

我想刪除任何字母和數字「清潔」緊接着他們如此對於上面的例子我想要:

1234 
1234 
1234 Supervisor 
1234 Administrator 

換句話說,我想保留最初的數字和最後一個詞。我使用的是SUBSTRINGCHARINDEX,但這些函數刪除了一切,直到字符串結尾,我不知道需要刪除的部分的長度。

有什麼建議嗎?

感謝

+0

初始數字部分是否始終爲4位數字? – 2010-08-19 20:42:20

+0

不,我不知道初始部分的長度。 – 2010-08-19 21:01:02

+0

我的基於解決方案比一個循環更好,並且處理任意數量的數字以及無數字,無字或僅有多個字 – 2010-08-19 21:18:58

回答

2

試試這個:

DECLARE @YourTable table (RowValue varchar(50)) 
INSERT @YourTable VALUES ('1234abc') 
INSERT @YourTable VALUES ('1234abcde456757') 
INSERT @YourTable VALUES ('1234abc Supervisor') 
INSERT @YourTable VALUES ('1234abc456 Administrator') 

UPDATE @YourTable 
    SET RowValue=LEFT(RowValue,4)+RIGHT(RowValue,CHARINDEX(' ',REVERSE(RowValue))) 
    FROM @YourTable 

SELECT * FROM @YourTable 

OUTPUT:

RowValue 
-------------------------------------------------- 
1234 
1234 
1234 Supervisor 
1234 Administrator 

(4 row(s) affected) 

編輯:一套基於任意數量的數字和處理無數字或無字

DECLARE @YourTable table (RowValue varchar(50)) 
set nocount on 
INSERT @YourTable VALUES ('13') 
INSERT @YourTable VALUES ('1234abc') 
INSERT @YourTable VALUES ('1234abc') 
INSERT @YourTable VALUES ('1234abcde456757') 
INSERT @YourTable VALUES ('1234abc Supervisor') 
INSERT @YourTable VALUES ('1234abc456 Administrator') 
INSERT @YourTable VALUES ('1234567abc456 Administrator') 
INSERT @YourTable VALUES ('Administrator') 
INSERT @YourTable VALUES ('abcde Administrator') 

set nocount off 

;WITH Digits AS 
(SELECT 0 AS Digit UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 

) 
,Numbers AS 
(SELECT 1 AS Number 
UNION ALL 
SELECT Number+1 FROM Numbers where Number<1000 
) 
,FindDigits AS 
(
SELECT 
    y.RowValue,n.Number,SUBSTRING(y.RowValue,n.Number,1) AS CharOf,CASE WHEN SUBSTRING(y.RowValue,n.Number,1) LIKE '[0-9]' THEN 'N' ELSE 'A' END AS TypeOf 
    FROM @YourTable   y 
     INNER JOIN Numbers n ON 1=1 
    WHERE n.Number<=LEN(y.RowValue) 
) 
,LenOf AS 
(
SELECT 
    RowValue,MIN(Number)-1 AS Digits 
    FROM FindDigits 
    WHERE TypeOf='A' 
    GROUP BY RowValue 
    HAVING MIN(Number)-1>0 
UNION 
SELECT 
    f.RowValue,LEN(f.RowValue) 
    FROM FindDigits f 
    WHERE NOT EXISTS (SELECT 1 FROM FindDigits f2 WHERE f.RowValue=f2.RowValue AND TypeOf='A') 
) 
UPDATE y 
    SET RowValue=CASE WHEN l.Digits IS NOT NULL THEN LEFT(y.RowValue,l.Digits)+RIGHT(y.RowValue,CHARINDEX(' ',REVERSE(y.RowValue))) 
         WHEN CHARINDEX(' ',REVERSE(y.RowValue))=0 THEN y.RowValue 
         ELSE RIGHT(y.RowValue,CHARINDEX(' ',REVERSE(y.RowValue))-1) END 
    FROM @YourTable  y 
     LEFT JOIN LenOf l ON y.RowValue=l.RowValue 
    OPTION (MAXRECURSION 1000) 

SELECT * FROM @YourTable 

OUTPUT:

RowValue 
-------------------------------------------------- 
13 
1234 
1234 
1234 
1234 Supervisor 
1234 Administrator 
1234567 Administrator 
Administrator 
Administrator 

(9 row(s) affected) 
+0

這假設初始位數是四位,不確定是否是這種情況! – Andomar 2010-08-19 20:45:32

+0

@KM - 感謝您的更新,我會試一試。 – 2010-08-20 15:01:02

0

你真的想兩個字符串,在指數0-3的人物和那些從空間,直到字符串結束後的位置。我(覺得)這個就可以了(還沒有嘗試過):

UPDATE TableName SET ColumnName = SUBSTRING(ColumnName,1,4) + 
    SUBSTRING(ColumnName,CHARINDEX(' ',ColumnName)+1,LEN(ColumnName)) 
+0

這不起作用,CHARINDEX的第一個參數是找到不是字符串來搜索的字符串,有'CHARINDEX(ColumnName,'')',請參閱[CHARINDEX(Transact-SQL)](http://msdn.microsoft.com/zh-cn/library/ms186323.aspx),更不用說您會發現第一個空格不是最後的 – 2010-08-19 20:44:00

+0

@KM修正了CHARINDEX。我認爲基於OP的問題,假設數據中只有一個空間是合理的。 – 2010-08-19 20:45:43

6

您可以搜索的第一個非數字,在子查詢第一空間。這同樣適用,如果位數不正是四:

declare @t table (col1 varchar(50)) 
insert into @t select '12abc' 
union all select '1234abcde456757' 
union all select '1234abc Supervisor' 
union all select '1234abc456 Administrator' 
union all select '123456abc456 Administrator' 

select case when FirstNonDigit = 0 then col1 
      when FirstSpace = 0 then substring(col1, 1, FirstNonDigit-1) 
      else substring(col1, 1, FirstNonDigit-1) + 
        substring(col1, FirstSpace, len(col1) - FirstSpace + 1) 
      end 
from (
     select patindex('%[^0-9]%', col1) FirstNonDigit 
     ,  patindex('% %', col1) FirstSpace 
     ,  col1 
     from @t 
     ) subqueryalias 

- >

12 
1234 
1234 Supervisor 
1234 Administrator 
123456 Administrator 
+1

非常好做:) – 2010-08-19 20:48:41

+0

謝謝。當這個值只是一個像「Administrator」這樣沒有數字或空格的字符串時也有效。我不知道桌子上有這樣的價值,但實際上它確實如此。 – 2010-08-19 21:05:28

+0

對'Administrator'(你得到一個前導空格)或'abc456 Administrator'這樣的值不起作用(得到一個完全空白的值) – 2010-08-19 21:16:57

0

下面的代碼使用值的「理貨表」查找第一個非數字字符和最後的空間。 KM的解決方案使用PATINDEX可能更優雅!

DECLARE @t TABLE 
(
    c VARCHAR(MAX) 
); 

INSERT INTO @t VALUES('1234abc'); 
INSERT INTO @t VALUES('1234abcde456757'); 
INSERT INTO @t VALUES('1234abc Supervisor'); 
INSERT INTO @t VALUES('1234abc456 Administrator'); 

WITH Tally AS 
(
    SELECT ROW_NUMBER() OVER (ORDER BY s1.[id]) AS i 
    FROM sys.sysobjects s1 CROSS JOIN sys.sysobjects s2 CROSS JOIN sys.sysobjects s3 
), 
NumPart AS 
(
    SELECT c, MIN(i) AS firstNonNumber 
    FROM @t CROSS JOIN Tally 
    WHERE i <= LEN(c) 
    AND SUBSTRING(c, i, 1) < '0' OR SUBSTRING(c, i, 1) > '9' 
    GROUP BY c 
), 
SpacePart AS 
(
    SELECT c, MAX(i) AS spacePos 
    FROM @t t CROSS JOIN Tally 
    WHERE i <= LEN(c) 
    AND SUBSTRING(c, i, 1) = ' ' 
    GROUP BY c 
) 
UPDATE t 
SET t.c = LEFT(n.c, n.firstNonNumber - 1) + 
    CASE WHEN ISNULL(s.SpacePos, 0) > 0 THEN 
     RIGHT(n.c, LEN(n.c) - s.SpacePos + 1) 
    ELSE 
     '' 
    END 
FROM @t t 
INNER JOIN NumPart n ON t.c = n.c 
LEFT JOIN SpacePart s ON n.c = s.c; 

SELECT * FROM @t;