我有一个从excel导入的csv文件。由于需要保留原始值,所有值都将作为varchar导入。现在我需要将货币值转换为十进制(18,4)。但是,许多行包含特殊字符(请参阅下面的简短列表)。
我想创建一个清除特殊字符并返回十进制数据类型的函数。这似乎是我应该面对和解决这个问题的许多人,我要求最好的方法来实现这一目标。
以下是我目前面临的一个小清单,我想知道除了 ($, - )领先空间,跟踪空间之外是否还有其他字符我应该考虑(S) :
$634,375.00
(104,055.00)
-139,686.03
(72,631.45)
17774137.14
8374187.29
$-7041078.47
下面是我正在努力帮助开发该函数的select语句:
SELECT i.[AsOfDate]
,COALESCE(case when len(ltrim(rtrim(i.[DealNum])))= 0 then null else i.[DealNum] end,
case when len(ltrim(rtrim(i.[CUSIP])))= 0 then null else i.[CUSIP] end,
case when len(ltrim(rtrim(i.[PoolNum])))= 0 then null else i.[PoolNum] end) AS [DealNum_CusIP_PoolNum]
,case when isnumeric(i.[Coupon]) = 1 then cast(i.[Coupon] as decimal(18,4)) else 0 end as [Coupon]
,case when isdate(i.[PurchaseDate]) = 1 then cast(i.[PurchaseDate] as date) else null end as [PurchaseDate]
,case when isdate (i.[SettleDate]) = 1 then cast(i.[SettleDate] as date) else null end as [SettleDate]
,case when isnumeric(Replace(Replace(ltrim(rtrim(i.[CurrentFace])),'(','-'),')','')) = 1 then cast(Replace(Replace(ltrim(rtrim(i.[CurrentFace])),'(','-'),')','') as decimal(18,4)) else 0 end as [CurrentFace]
,case when isnumeric(i.[PurchasePrice]) = 1 then cast(i.[PurchasePrice] as decimal(18,4)) else 0 end as [PurchasePrice]
,case when isnumeric(i.[CurrentPrice]) = 1 then cast(i.[CurrentPrice] as decimal(18,4)) else 0 end as [CurrentPrice]
,case when isnumeric(i.[RealizedGL]) = 1 then cast(i.[RealizedGL] as decimal(18,4)) else 0 end as [RealizedGL]
,case when isnumeric(Replace(i.[Premium],'$','')) = 1 then cast(Replace(i.[Premium],'$','') as decimal(18,4)) else 0 end as [Premium]
,case when isnumeric(i.[OLMTM]) = 1 then cast(i.[OLMTM] as decimal(18,4)) else 0 end as [OLMTM]
,case when isnumeric(i.[CurrentMTM]) = 1 then cast(i.[CurrentMTM] as decimal(18,4)) else 0 end as [CurrentMTM]
FROM [import].[Openlink_Position_Detail] I
到目前为止,这是我所拥有的,但它仍然没有完全发挥作用:
CREATE FUNCTION Stage.CleanForDecimal
(
@input varchar(100)
)
RETURNS decimal(18,4)
AS
BEGIN
DECLARE @rv as decimal(18,2), @wv as varchar(100)
SELECT @wv = ltrim(rtrim(@input));
SELECT @wv = replace(@input,'$','');
SELECT @wv = replace(@input,',','');
SELECT @wv = replace(@input,'(','-');
SELECT @wv = replace(@input,')','');
SELECT @rv = case when isnumeric(@wv) = 1 then cast(@wv as decimal(18,4)) else 0 end
-- Return the result of the function
RETURN @rv
END
答案 0 :(得分:1)
以前在Excel中使用格式化的货币字符串。然后开发人员提到了SQL Server 2012中引入的TRY_PARSE
:
CAST(TRY_PARSE(MyColumn AS money USING 'en-US') AS float)
这适用于空格,美元符号,逗号和括号。它适用于您提供的所有样本数据,但不会使用欧元符号作为示例。
您不应该使用money
因为所有计算都会舍入到2位小数,即使在中间步骤中也是如此。在这里,它仅用于方便。
答案 1 :(得分:0)
以下是更正的功能:
ALTER FUNCTION [Stage].[CleanForDecimal]
(
@input varchar(100)
)
RETURNS decimal(18,4)
AS
BEGIN
DECLARE @rv as decimal(18,4), @wv as varchar(100)
SELECT @wv = ltrim(rtrim(@input));
SELECT @wv = replace(@wv,'$','');
SELECT @wv = replace(@wv,',','');
SELECT @wv = replace(@wv,'(','-');
SELECT @wv = replace(@wv,')','');
SELECT @rv = case when isnumeric(@wv) = 1 then cast(@wv as decimal(18,4)) else 0 end
RETURN @rv
/* execution example:
select Stage.CleanForDecimal(' ($123,44.2345)')
*/
END
答案 2 :(得分:0)
FWIW这是针对同样问题的Oracle解决方案。当然你不能按原样使用它,但也许你可以使用我们如何处理问题的逻辑。信息就是力量!
/********************************************************************************************************
Name: STR_TO_NUMBER
Desc: Converts a string to a number, stripping dollar signs, commas and converting if a negative is
shown by parentheses. Used when converting data froma spreadsheet where
the format shows negatives in parens.
Args: string_in IN VARCHAR2
Returns: NUMBER
Usage: SELECT thc_utl.str_to_number('(1,234.56)')
FROM dual;
REVISIONS:
Ver Date Author Description
--------- ---------- --------------- ------------------------------------
1.0 12/12/2014 Gary_W - Created function.
************************************************************************************************************************/
FUNCTION STR_TO_NUMBER(string_in IN VARCHAR2) RETURN NUMBER AS
v_nbr NUMBER;
BEGIN
-- TRIM the string, then
-- strip commas with REPLACE()
-- strip dollar signs with REPLACE()
-- then take what's in the parens, add a negative sign and make it a number.
v_nbr := to_number(regexp_replace(replace(replace(TRIM(string_in),','),'$'), '^\(([^)]+)\)$', '-\1'));
RETURN v_nbr; -- Return the converted number.
END STR_TO_NUMBER;
Gary_W穿上防火服并等待回复。
答案 3 :(得分:0)
这是基于JAC输入的另一种解决方案。
declare @somestring as varchar(100)
set @somestring = ' ($123,234.5567)'
Select isnull(CAST(TRY_PARSE(@somestring AS money USING 'en-US') AS decimal(18,4)),0) as rv
-- returns -123234.5567
set @somestring = ' ($123,2fubar34.5567)'
Select isnull(CAST(TRY_PARSE(@somestring AS money USING 'en-US') AS decimal(18,4)),0) as rv
-- returns 0.0000
我不确定这是否比我之前发布的功能更有效,但我希望它可以帮助其他人解决这个问题。