从Varchar列中删除字母数字字符,然后转换为Float

时间:2013-12-05 11:01:47

标签: sql sql-server tsql sql-server-2012

我有一个包含120列的实验室测试表,所有列都有数据类型varchar(应该是FLOAT),但这些列还包含^,*,A-Z,a-z,逗号,满句子等字符停 ”。”在末尾。我使用以下函数来保存所有数值,包括“。”。

问题是这个.(点),如果我使用@KeepValues as varchar(50) = '%[^0-9]%'那么它会删除所有点(例如1.05*L成为105)这不是我的东西想。

请你帮我解决这个问题非常有帮助,或者任何其他解决办法都很棒

Create Function [dbo].[RAC]
    (@Temp VarChar(1000))
Returns VarChar(1000)
AS
Begin
    Declare @KeepValues as varchar(50) = '%[^0-9.]%'

    While PatIndex(@KeepValues, @Temp) > 0
        Set @Temp = Stuff(@Temp, PatIndex(@KeepValues, @Temp), 1, '')

    Return @Temp
End

我的T-SQL CASE声明是:

 ,CASE WHEN LTRIM(RTRIM(DBO.RAC([INR]))) NOT IN ('','.') 
       THEN round(AVG(NULLIF(CAST(DBO.RAC([INR]) as FLOAT), 0)), 2) 
  END AS [INR]

3 个答案:

答案 0 :(得分:3)

由于您拥有SQL2012,因此您可以利用TRY_CONVERT()函数

CREATE FUNCTION [dbo].[RAC] (@input varchar(max))
RETURNS TABLE AS
RETURN (
  WITH number_list AS (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 1)) i FROM sys.objects a)
  SELECT TOP 1 TRY_CONVERT(float,LEFT(@input,i)) float_conversion
  FROM number_list
  WHERE i <= LEN(@input) AND TRY_CONVERT(float,LEFT(@input,i)) IS NOT NULL
  ORDER BY i DESC
)
GO

如果您有一个非常有用的实际number_list,请改用它。

DECLARE @table TABLE (data varchar(max))
INSERT @table VALUES
('123.124'), 
('123.567 blah.'),
('123.567E10 blah.'),
('blah 45.2')

SELECT *
FROM @table
OUTER APPLY [dbo].[RAC](data) t

答案 1 :(得分:3)

你需要一个基本的正则表达式,它允许你获得两组数字之间只有一个小数的数字(或者可能是完全没有小数的数字)。这需要将SQLCLR用于RegEx功能。您可以找到许多这样的示例,或者您可以使用免费提供的SQLCLR库SQL# (SQLsharp)(我是其作者,但回答此问题所需的功能在免费版本中)。

DECLARE @Expression NVARCHAR(100) = N'\d+(\.\d+)?(e[-+]?\d+)?';

SELECT
    SQL#.RegEx_MatchSimple(N'This is a test. Number here 1.05*L.',
          @Expression, 1, 'IgnoreCase') AS [TheNumber],
    CONVERT(FLOAT, SQL#.RegEx_MatchSimple(N'This is a test. Number here 1.05*L.',
          @Expression, 1, 'IgnoreCase')) AS [Float],
    CONVERT(FLOAT, SQL#.RegEx_MatchSimple(N'Another test. New number 1.05e4*L.',
          @Expression, 1, 'IgnoreCase')) AS [Float2],
    CONVERT(FLOAT, SQL#.RegEx_MatchSimple(N'One more test. Yup 1.05e-4*L.',
          @Expression, 1, 'IgnoreCase')) AS [Float3]

/*
Returns:
    TheNumber   Float       Float2      Float3
    1.05        1.05        10500       0.000105
*/

模式的唯一问题是如果文本中有另一个数字(你确实说有完整的句子),那么你想要的那个。如果您100%确定所需的值始终具有小数,则可以使用更简单的表达式,如下所示:

\d+\.\d+(e[-+]?\d+)?

正则表达式允许使用可选的(e / e + / e-)表示法。

答案 2 :(得分:2)

PATINDEX支持模式匹配,但仅适用于T-SQL模式,并且获取模式以执行所需操作可能是不可能的。 听起来你需要使用正则表达式,你需要一个CLR用户定义的函数,或者你可以通过编写一个应用程序使用SQL Server的外部来实现它。

this question的明确答案将帮助您获得所需内容。

以下是代码的副本,以便于参考:

using System;  
using System.Data;  
using System.Text.RegularExpressions;  
using System.Data.SqlClient;  
using System.Data.SqlTypes;  
using Microsoft.SqlServer.Server;  

public partial class UserDefinedFunctions  
{  
    [Microsoft.SqlServer.Server.SqlFunction]  
    public static SqlString StripNonNumeric(SqlString input)  
    {  
        Regex regEx = new Regex(@"\D");  
        return regEx.Replace(input.Value, "");  
    }  
};