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

问题描述 投票:0回答:3

我有一个包含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]
sql sql-server tsql sql-server-2012
3个回答
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

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
投票

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, "");  
    }  
};
© www.soinside.com 2019 - 2024. All rights reserved.