2010-08-19 2 views
4

У меня есть varchar колонки в одной из моих таблиц с данными, такими как:T-Sql запрос, чтобы очистить VARCHAR столбец

1234abc 
1234abcde456757 
1234abc Supervisor 
1234abc456 Administrator 

Я хочу, чтобы «очистить его», удаляя любые буквы и цифры, сразу же после их так для приведенных выше примеров, которые я хочу иметь:

1234 
1234 
1234 Supervisor 
1234 Administrator 

в другом слове, я хочу сохранить начальное число и последнее слово. Я использую SUBSTRING и CHARINDEX, но эти функции удаляют все до конца строки, и я не знаю длины части, которую мне нужно удалить.

Любые предложения?

Благодаря

+0

Является ли начальная цифра длиной 4 цифры длиной? –

+0

Нет. Я не знаю длины внутренней части. –

+0

мое решение на основе набора лучше, чем цикл, и обрабатывает любое количество цифр, а также цифр, слов или нескольких слов только –

ответ

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) 

EDIT: набор на основе любого количества цифр и не обрабатывает цифры или нет слов

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 
44445164 +10617451515053691368888

ВЫВОД:

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

(9 row(s) affected) 
+0

Предполагает, что число начальных цифр равно четырем, не уверен, что так! – Andomar

+0

@KM - Спасибо за обновление, я попробую. –

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/en-us/library/ms186323.aspx), не говоря уже о том, что вы находите первое пространство не последний –

+0

@ KM фиксированный CHARINDEX. Я подумал, что, основываясь на вопросе ОП, разумно предположить, что в данных было только одно пространство. –

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

Очень красиво сделано :) –

+0

Спасибо. Также работает, когда значение представляет собой только строку типа «Администратор» без номеров или пробелов. Я не знал, что таблица имеет такие ценности, но, скорее всего, так и было. –

+0

не работает для таких значений, как 'Administrator' (вы получаете ведущее пространство) или' abc456 Administrator' (получите полное значение) –

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; 
Смежные вопросы