将多种格式的字符串转换为单一的标准格式

时间:2013-01-18 16:05:13

标签: sql sql-server tsql

我使用从SSRS导入信息的存储过程更新表。我有一个名为page的字段。页面字段可以包含以下三种格式之一:

  1. 纯粹的数字字段,例如1,2 3等。
  2. 数字和字母组合,例如1D,4C,7Z等。
  3. 数字,短划线和两个额外的数字,例如2-01,3-04,1-09等
  4. 我需要为每种格式创建页面等效性以进行排序,以及帮助定义一般类别的页码。示例1是基页,示例2是艺术页面,示例3是文本页面。

    对于等价,示例1将导致1.00格式。示例2将基于字母的等效数字得到1.01到1.26当量。最后,示例3将导致破折号右侧的值为1.26加上.01 *。最小值为1.27。

    我在Excel中完成了这项工作,但似乎无法在SQL中正确编写公式。

    我正在使用SQL Server 2008 R2

3 个答案:

答案 0 :(得分:1)

这似乎涵盖了您描述的案例:

declare @t table (val varchar(10))
insert into @t 
select '1' union select '2' union
select '1D' union select '4S' union
select '2-01' union select '1-09'

select val, case
    when val not like '%[^0-9]%' then val + '.00'
    when val like '[0-9][A-Z]' then '1.' + right('0' + convert(varchar, ascii(right(val, 1))-64), 2)
    when val like '%-%' then convert(varchar, 1.26 + (0.01 * cast(substring(val, charindex('-', val)+1, 2) as int)))
    else val end
from
    @t

TSQL不是字符串操作和解析的好语言,因此您可能需要考虑使用CLR函数或存储过程。应用这些规则是单元测试的理想选择,因为定义和使用输入和输出值的测试集来验证代码很简单。

答案 1 :(得分:1)

这是另一种选择。

虽然此答案基于Pondlife's,但它会返回decimal个结果而不是字符串。

它大量使用隐式转换,这就是它看起来更紧凑的原因。

它还假设只使用了问题中提到的三种格式。如果某个值的格式为“无效”,则会破坏此解决方案。

SELECT
  CASE
    WHEN PageNo NOT LIKE '%[^0-9]%' THEN PageNo
    WHEN PageNo     LIKE '%[A-Z]'   THEN LEFT(PageNo, LEN(PageNo) - 1)
                                         + (ASCII(RIGHT(PageNo, 1)) - 64) * 0.01
    WHEN PageNo     LIKE '%-%'      THEN REPLACE(PageNo, '-', '.') * 1.0 + 0.26
  END
FROM ...

答案 2 :(得分:0)

这很丑陋,可能效率不高,但是:

select
  page_num,
  case
    when page_num like '%A' then substring(page_num, 1, len(page_num)-1) + '.01'
    when page_num like '%B' then substring(page_num, 1, len(page_num)-1) + '.02'
    when page_num like '%C' then substring(page_num, 1, len(page_num)-1) + '.03'
    when page_num like '%D' then substring(page_num, 1, len(page_num)-1) + '.04'
    when page_num like '%E' then substring(page_num, 1, len(page_num)-1) + '.05'
    when page_num like '%F' then substring(page_num, 1, len(page_num)-1) + '.06'
    when page_num like '%G' then substring(page_num, 1, len(page_num)-1) + '.07'
    when page_num like '%H' then substring(page_num, 1, len(page_num)-1) + '.08'
    when page_num like '%I' then substring(page_num, 1, len(page_num)-1) + '.09'
    when page_num like '%J' then substring(page_num, 1, len(page_num)-1) + '.10'
    when page_num like '%K' then substring(page_num, 1, len(page_num)-1) + '.11'
    when page_num like '%L' then substring(page_num, 1, len(page_num)-1) + '.12'
    when page_num like '%M' then substring(page_num, 1, len(page_num)-1) + '.13'
    when page_num like '%N' then substring(page_num, 1, len(page_num)-1) + '.14'
    when page_num like '%O' then substring(page_num, 1, len(page_num)-1) + '.15'
    when page_num like '%P' then substring(page_num, 1, len(page_num)-1) + '.16'
    when page_num like '%Q' then substring(page_num, 1, len(page_num)-1) + '.17'
    when page_num like '%R' then substring(page_num, 1, len(page_num)-1) + '.18'
    when page_num like '%S' then substring(page_num, 1, len(page_num)-1) + '.19'
    when page_num like '%T' then substring(page_num, 1, len(page_num)-1) + '.20'
    when page_num like '%U' then substring(page_num, 1, len(page_num)-1) + '.21'
    when page_num like '%V' then substring(page_num, 1, len(page_num)-1) + '.22'
    when page_num like '%W' then substring(page_num, 1, len(page_num)-1) + '.23'
    when page_num like '%X' then substring(page_num, 1, len(page_num)-1) + '.24'
    when page_num like '%Y' then substring(page_num, 1, len(page_num)-1) + '.25'
    when page_num like '%Z' then substring(page_num, 1, len(page_num)-1) + '.26'
    when page_num like '%-%' then 
      substring(page_num, 1, charindex('-', page_num)-1) + '.' + 
      cast((26+cast(substring(page_num, charindex('-', page_num)+1, len(page_num)) as int)) as varchar(12))                                                                                                          
    else page_num + '.00'
  end
from pages

有关我正在测试的完整架构,请参阅SQL Fiddle

也就是说,我强烈建议您将架构更新为包含规范化页码的内容,并在进入表格的过程中将其转换。