如何使用SQL Server查询从单词中分离字符和数字

时间:2019-03-12 07:13:32

标签: sql sql-server tsql

如何使用SQL Server查询从单词中分离字符和数字?

单词示例:AB12C34DE

输出类似于:

col1
-----    
ABCDE

col2
-----
1234

3 个答案:

答案 0 :(得分:2)

像这样尝试:

DECLARE @word VARCHAR(100)='AB12C34DE';

WITH Tally(Nmbr) AS
(
    SELECT TOP(LEN(@word)) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values
)
,Separated AS
(
    SELECT CASE WHEN OneChar LIKE '[0-9]' THEN 1 ELSE 0 END AS IsDigit
          ,OneChar
          ,Nmbr
    FROM Tally
    CROSS APPLY(SELECT SUBSTRING(@word,Nmbr,1)) A(OneChar)
)
SELECT (SELECT OneChar AS [*] FROM Separated WHERE IsDigit=1 ORDER BY Nmbr FOR XML PATH(''),TYPE).value('.','nvarchar(max)') AS AllNumbers
      ,(SELECT OneChar AS [*] FROM Separated WHERE IsDigit=0 ORDER BY Nmbr FOR XML PATH(''),TYPE).value('.','nvarchar(max)') AS AllCharacters;

一些解释

该想法使用了一个理货表格(数字列表)。您可以使用现有的物理数字表...

  • 第一个CTE“理货”将创建一个派生的数字列表(1、2、3,...),每个字符一个。
  • 第二个CTE将逐个读取每个字符 并将其标记为数字。
  • 最终查询将重新连接字符列表

答案 1 :(得分:1)

由于您正在使用SQL Server 2012,因此不能使用TRANSLATE来简化此操作。

一种方法是使用REPLACE,如下所示。如果需要,可以将其转换为用户定义的function,这样就不必一次又一次地写相同的东西。

DECLARE @TABLE TABLE(VAL VARCHAR(100))
INSERT INTO @TABLE SELECT 'AB12C34DE'

SELECT REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE (VAL, '0', ''),
'1', ''),
'2', ''),
'3', ''),
'4', ''),
'5', ''),
'6', ''),
'7', ''),
'8', ''),
'9', '') COL1,
REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE (VAL, 'A', ''),
'B', ''),
'C', ''),
'D', ''),
'E', ''),
'F', ''),
'6', ''),
'G', ''),
'H', ''),
'I', '') COL2
--ADD OTHER CHARACTERS

FROM @TABLE

答案 2 :(得分:1)

这似乎是使用递归CTE的好地方:

with cte as (
      select v.str, convert(varchar(max), '') as digits, convert(varchar(max), '') as chars, 1 as lev
      from (values ('AB12C34DE')) v(str)
      union all
      select stuff(str, 1, 1, ''),
             (case when left(str, 1) like '[0-9]' then digits + left(str, 1) else digits end),
             (case when left(str, 1) like '[a-zA-Z]' then chars + left(str, 1) else chars end),
             lev + 1
      from cte
      where str > ''
     )
select top (1) with ties cte.*
from cte
order by row_number() over (order by lev desc);

正如values()子句所建议的那样,这将适用于表中的列以及常量。