T-Sql查询清理varchar列

时间:2010-08-19 20:21:21

标签: sql-server-2005 tsql string

我的一个表格中有一个varchar列,其数据如下:

1234abc
1234abcde456757
1234abc Supervisor
1234abc456 Administrator

我希望通过删除紧随其后的任何字母和数字来“清理它”,以便我想要的上述示例:

1234
1234
1234 Supervisor
1234 Administrator

换句话说,我想保留最初的数字和最后一个字。我正在使用SUBSTRINGCHARINDEX,但这些函数会删除所有内容,直到字符串结尾,我不知道需要移除的部分的长度。

有什么建议吗?

由于

4 个答案:

答案 0 :(得分: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 :(得分: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

输出:

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

输出:

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

(9 row(s) affected)

答案 2 :(得分:0)

你实际上想要两个字符串,索引0-3处的字符和从空格之后的位置直到字符串结尾的字符。我(想)这会起作用(没试过):

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

答案 3 :(得分:0)

下面的代码使用值的“计数表”来查找第一个非数字字符和最后一个空格。使用PATINDEX的KM解决方案可能更优雅!

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;