【问题标题】:Correct type of data for latitude and longtitude SSIS ETL process经纬度 SSIS ETL 过程的正确数据类型
【发布时间】:2021-04-30 17:25:21
【问题描述】:

我正在尝试通过我创建的 ETL 过程将纬度和经度数据转换并上传到数据库中,在该过程中,我们从 .csv 文件中获取源数据并将其转换为 DECIMAL。下面是两个值的示例:

Latitude (first column): 41.896585191199556  
Longitude (second column):-87.66454238198166

我将数据库的数据类型设置为:

Latitude DECIMAL(10,8)
Longitude DECIMAL(11,8)

当我尝试将数据从文件转换到数据库时出现主要问题,然后我收到消息 [Flat File Source [85]] Error: Data conversion failed. The data conversion for column "Latitude" returned status value 2 and status text "The value could not be converted because of a potential loss of data.".

查看我的流程:

当试图忽略错误时,数据库中的纬度和经度值被更改为 NULL...平面文件编码为 65001。 我尝试对数据类型进行转换:float、DECIMAL、int 并没有任何帮助。 我的问题是:

  1. 我应该在目标数据库中为上述这些值使用什么数据类型。
  2. 我应该在输入平面文件时选择什么数据类型?
  3. 为转换设置什么数据类型(我怀疑我们将在数据库中使用的数据类型)?

请注意文件中的某些记录缺少位置

  • 从数据查看:
  • 从数据转换查看:

更新

运行 FastParse 时,我收到如下错误消息:

在这种情况下我应该选择什么数据类型?我按照@billinkc 的建议设置了所有内容。当我设置一个整数时,例如 DT_I4,它会导致 NULL 和与以前相同的错误(在此消息中,无法为 Latitude 的值选择某种数据类型,即 DECIMAL 或 STRING)。

【问题讨论】:

  • 您是如何定义平面文件连接管理器中的列的。默认情况下,它将是字符串。你提到 65001 文件编码 - 你在什么 Windows 区域设置(如果不是以美国为中心)?
  • @billinkc 我用数据库中出现的类型定义了列,例如纬度十进制。 Windows 位于欧洲中部

标签: sql ssis etl


【解决方案1】:

您需要DECIMAL(11,8)。小数点之前有三位数字,之后有一个数字。

当您的经度大于 100 或小于 -100 时,无疑会发生转换失败。

【讨论】:

  • 我按照您的建议设置了 DECIMAL(11,8),但一旦被忽略,仍然会得到相同的错误和 NULL 值
  • @lechsollagos 。 . .在这种情况下,您可能需要将其作为字符串导入并查看列中的实际内容。
  • 这太可怕了,但我已经尝试使用第 26 个平面文件管理器进行大量组合但没有任何效果...... 4 小时后,我开始怀疑这是否可行......我用 String 尝试了这个解决方案但仍然是同样的错误
【解决方案2】:

报告的错误表明故障点是平面文件源

[平面文件源 [85]] 错误:数据转换失败。 “纬度”列的数据转换返回状态值 2 和状态文本“由于可能丢失数据,无法转换该值。”。

我使用的是美国语言环境机器,因此您可能遇到小数分隔符问题。如果是这种情况,那么在您的平面文件源中,右键单击并选择显示高级编辑器。转到输入和输出属性,然后在平面文件源输出下,展开输出列,对于每个浮点数列,检查FastParse 选项。

如果可行,那太好了,您有一个有效的平面文件源。

我能够以两种不同的方式实现这一点。我在我的包中定义了两个平面文件连接管理器:FFCM DecFFCM String 虽然我更喜欢尽量减少我应用到我的包的操作和转换的数量,但将数据类型声明为字符串可以帮助您克服“由于数据不正确,我什至无法启动数据流”

源数据

我创建了一个保存为 UTF-8 的 CSV

Latitude,Longitude
41.896585191199556,-87.66454238198166

FFCM 十二月

我配置了一个标准的 CSV

我用DT_DECIMALDataType 定义了我的列

FFCM 字符串

首页相同,但在高级部分的列中,我将数据类型保留为 DT_WSTR,长度为 50

至此,我们已经定义了源数据结构的基本属性。

目的地

我对目的地的尺寸保持一致。使用 10 与 11 不会节省任何东西,而且我懒得查找允许的经纬度数域

CREATE TABLE dbo.SO_65909630 
(
    [Latitude] decimal(18,15)
,   [Longitude] decimal(18,15)
)

数据流

我需要运行,但您要么在输入时使用正确键入的数据 (DFT DEC),要么转换它。

我在您的源数据中看到的空白可能需要处理(您有需要转义的列或没有数据 - 这将导致数据转换失败,所以我提倡这种方法

行计数只是为了在我构建答案时提供一个放置数据查看器的地方

我应该为 lat 和 long 使用什么数据类型

Decimal 是一种精确的数据类型,因此它将存储您提供的 exact 值。使用时采用decimal(scale, precision) 的形式。在担任当前职位之前,我从未使用过任何其他数据类型来表示非整数。

十进制和数字在线书籍 (Transact-SQL) https://docs.microsoft.com/en-us/sql/t-sql/data-types/decimal-and-numeric-transact-sql?view=sql-server-ver15

规模

要存储的十进制数字的最大总数。这个数字包括小数点的左边和右边。精度必须是从 1 到最大精度 38 之间的值。默认精度是 18。

精度

小数点右侧存储的小数位数。从 p 中减去该数字以确定小数点左侧的最大位数。 Scale 必须是从 0 到 p 的值,并且只能在指定精度的情况下指定。默认比例为 0,因此 0

Precision   Storage bytes

1 - 9           5
10-19           9
20-28          13
29-38          17

对于我在上面定义的表格,存储每个 lat/long 将花费我们 18 个字节 (2 * 9)。

但是让我们看看实际的纬度和经度域(在地球上) 这个关于 GIS.se 的精彩答案被打印出来并挂在我的工作监视器 https://gis.stackexchange.com/questions/8650/measuring-accuracy-of-latitude-and-longitude

在此处粘贴相关位

  • 小数点后六位的值最高为 0.11 m:您可以使用它来详细布置结构、设计景观、修建道路。它应该足以跟踪冰川和河流的运动。这可以通过对 GPS 采取艰苦的措施来实现,例如差分校正 GPS。
  • 小数点后七位最高可达 11 毫米:这对于大量测量来说是有利的,并且接近基于 GPS 的技术所能达到的极限。
  • 小数点后八位 最高可达 1.1 毫米:这对于绘制构造板块运动和火山运动的图表非常有用。永久性、经过校正、持续运行的 GPS 基站或许能够达到这种准确度。
  • 小数点后第九位的值高达 110 微米:我们正在进入显微镜的范围。对于几乎所有可以想到的具有地球位置的应用,这都是多余的,而且比任何测量设备的精度都要精确。
  • 十位或更多小数表示使用了计算机或计算器,并且没有注意额外的小数是无用的事实。请小心,因为除非您是从设备上读取这些数字的人,否则这可能表明处理质量低下!

您的输入值显示超过 10 位的精度,所以我猜这是一个计算值,而不是“真正的观察”。这很好,这给了我们更多的工作空间。

为什么,我们可以将下面的十进制声明调低一半*第一个的存储成本

CREATE TABLE dbo.SO_65909630_alt
(
    [Latitude] decimal(8,5)
,   [Longitude] decimal(8,5)
);

这很好,我们以更低的成本存储了“相同”的数据。也许您的用例只是“我的商店在哪里”,即使您是拥有不到 12000 家商店的沃尔玛,谁在乎呢?这是微不足道的成本。但是,如果您还需要存储他们客户的坐标,那么每条记录的存储成本可能就很重要了。或者在您阅读本文时使用亚马逊或阿里巴巴或任何存在的非常大的消费者零售商。

在我的工作中,我处理气象数据,它有各种形状和大小,但对我来说,一个常见的来源是Stage IV data只是美国毗连的每小时降雨量。因此,每天每个坐标有 24 个读数。坐标系为 1121 x 881(987,601 点),因此表示美国一天的每小时降雨量为 23,702,424 行。鉴于 Stage IV 数据可追溯到 2008 年,因此 18 字节与 10 字节之间的差异很快就会变得明显。

我们实际上使用float(或实数)来存储纬度和经度值,因为它为每个坐标节省了 2 个字节。

CREATE TABLE dbo.SO_65909630_float
(
    [Latitude] float(24)
,   [Longitude] float(24)
);

INSERT INTO dbo.SO_65909630_alt
(
    Latitude
,   Longitude
)
SELECT * FROM dbo.SO_65909630 AS S

现在,这让我很痛苦,因为浮点数很有趣,我无法在查询中使用精确过滤器。

我的十进制类型表中有这个

41.89659    -87.66454

我的浮动类型表里面有这个

41.89658    -87.66454

您是否注意到纬度中最后一位数字的变化? 8 不是 9,因为十进制表有,但无论哪种方式,都没有关系

SELECT * FROM dbo.SO_65909630_float AS S WHERE S.Latitude = 41.89658

由于浮点舍入完全匹配废话,这不会找到一行。相反,您的查询变成了范围很窄的查询,例如

SELECT * FROM dbo.SO_65909630_float AS S WHERE S.Latitude >= (41.89658 - .00005) AND S.Latitude <= (41.89658 + .00005)

.00005 是一个值,您必须根据您的数据进行试验,以确定您需要调整多少数字才能再次找到它。

最后,不管怎样,如果您将 lat 和 long 转换为 Geography Point,它将强制输入数据类型按原样浮动。

【讨论】:

  • 非常感谢您的澄清 - 现在我对这个主题的了解比以前更多了。我的另一个请求 - 你能看看最新的答案吗?我遇到了这个平面文件的下一个问题
  • FastParse 只是一个想法,但正如错误消息所说,它与数据类型不兼容。如果您在我在此处显示的平面文件源中定义为字符串或十进制,则该包有效。使用相同的样本数据并制作一个微小的复制包(在平面文件连接管理器中将列定义为字符串并在包中进行转换,或者在平面文件连接管理器中将类型定义为十进制)。如果可行,那么您将慢慢增加复杂性,直到您确定是什么导致您的完整包失败
猜你喜欢
  • 2010-11-14
  • 2010-09-27
  • 1970-01-01
  • 2011-12-30
  • 2021-06-08
  • 1970-01-01
  • 2019-08-03
  • 1970-01-01
  • 2012-03-22
相关资源
最近更新 更多