我目前正在从事ETL项目,该项目将mongoDB中的数据转换为关系数据库并存储在SQL Server中。我遇到的问题是mongoDB中同一字段中的一些数字存储为十进制(0.058823),有时使用科学计数法(5.8823e-02)。
当我使用Postgres时,任一种格式的值都以双精度值形式传递,并且在使用任一种格式进行查询时都没有问题。 SQL Server似乎并非如此。
当前所有数据都以varchar
的形式传递,并且在同一张表的视图中,我正在使用以下代码:
CAST (CASE
WHEN [fieldname] LIKE '%e%'
THEN log([fieldname])
ELSE [fieldname]
END AS DECIMAL(30, 20)) AS [FieldName1]
在我要转换为子字符串和强制转换的字段中也有列表,这需要使用CTE。这将我的代码从100多行变成了近600多行。想知道是否有更简单的方法?
非常感谢您能提供的任何帮助。
答案 0 :(得分:4)
SQL Server支持科学计数法和“常规”小数。
这是一个简单的例子:
DECLARE @D decimal(10, 6) = 0.058823,
@S decimal(10, 6) = 5.8823e-02
SELECT @D As Regular,
@S As Scientific,
IIF(@D = @S, 1, 0) As AreEqual
此选择语句的结果是:
Regular Scientific AreEqual
0.058823 0.058823 1
但是,将varchar
强制转换为十进制与常规十进制完美配合,但是使用科学计数法会引发错误:
DECLARE @SD varchar(10) = '0.058823',
@SS varchar(10) = '5.8823e-02'
SELECT CAST(@SD AS decimal(10, 6)) As RegularString,
CAST(@SS AS decimal(10, 6)) As ScientificString
引发此错误:
将数据类型varchar转换为数字时出错。
另一方面,强制转换为float可以很好地工作-因此,要获得小数,可以先转换为float再转换为十进制:
SELECT CAST(@SD AS decimal(10, 6)) As RegularString,
CAST(CAST(@SS AS float) AS decimal(10, 6)) As ScientificString
结果:
RegularString ScientificString
0,058823 0,058823
答案 1 :(得分:0)
由于您的主要关注点似乎是代码膨胀(600行vs. 100行),因此您可以创建一个函数
CREATE FUNCTION dbo.GetDecimal(@input VARCHAR(32))
RETURNS DECIMAL(30,20)
AS
BEGIN
RETURN CAST(CAST(@input AS FLOAT) AS DECIMAL (30, 20))
END
并在SELECT语句中为要转换的每个字段调用它,如下所示:
SELECT
dbo.GetDecimal(sfield1) as tfield1,
dbo.GetDecimal(sfield2) as tfield2,
...
FROM ...
注意:对您的问题的第一条评论正确指出,您不应使用log()函数。而是,此用户函数执行中间强制转换,以在最终强制转换为十进制之前浮动。这是必要的,因为用科学计数法表示的字符串值不能直接转换为十进制。