如何从 Snowflake 中的 varchar 列动态 trim 小数位?

How to dynamically trim decimal places from varchar column within Snowflake?

我 运行 遇到了一个我真的很困惑的问题。我们将面积点存储在 Snowflake 中的 1 列内。

存储为 varchar 的示例:

多边形((( -103.13610284560149 32.725882872864453 , -103.14470012813675 ​​32.725738931539986 , -103.14475163540753 32.732599004640321 , -103.13626891853778 32.732448970077257 , -103.1361028456015 32.725882872864453 , -103.13610284560149 32.725882872864453)))

Snowflake 有一些内置的 Geography/Geospatial 功能,但是它不允许一个区域有重叠线。

SELECT TO_GEOGRAPHY('MULTIPOLYGON (((
  -103.13610284560149 32.725882872864453
, -103.14470012813675 32.725738931539986
, -103.14475163540753 32.732599004640321
, -103.13626891853778 32.732448970077257
, -103.1361028456015  32.725882872864453
, -103.13610284560149 32.725882872864453)))')

运行 Snowflake 上面的代码 returns:

SQL 错误 [100217] [P0000]:地理验证失败:边 (-103.136103,32.725883) -- (-103.144700,32.725739) 穿过边 (-103.136269,32.732449) -- (-103.136103 ,32.725883)

这个区域有 6 个点,点 #5 几乎在点 6 之上,所以它重叠并抛出错误。我已经要求关心这些数据的业务领域尝试以较低的精度存储数据,因为小数点后 13 位太准确了,但我的任务是如何清理它。

这些区域是独一无二的,但大多数是正方形,但它们可以有任意数量的点。有3分到5万多的区域。我已经使用 Snowflake 的 SPLIT_TO_TABLE 尝试将每个坐标对解析为它们自己的行,但是我无法将后续行拆分出来。

我有 运行 这个:

CREATE OR REPLACE TABLE DATABASE.SCHEMA.GEOGRAPHYSTUFF AS
SELECT  table1.value
FROM TABLE(split_to_table(
(
SELECT 'MULTIPOLYGON (((
  -103.13610284560149 32.725882872864453
, -103.14470012813675 32.725738931539986
, -103.14475163540753 32.732599004640321
, -103.13626891853778 32.732448970077257
, -103.1361028456015  32.725882872864453
, -103.13610284560149 32.725882872864453)))'
), ',')) AS table1;
   

   WITH cte AS (
   SELECT SPLIT(VALUE, ' ')::VARCHAR AS POINTS
   FROM DATABASE.SCHEMA.GEOGRAPHYSTUFF
   )
   
   Select SPLIT(POINTS, ',')
   FROM cte 
   

其中包含特殊字符,粘贴后如下所示:

[
  "[\"MULTIPOLYGON\"",
  "\"(((\r\n\"",
  "\"\"",
  "\"-103.13610284560149\"",
  "\"32.725882872864453\r\n\"]"
]

我不确定这是否可以在 Snowflake 中完全解决。我在想我可能需要使用 Python 或 PowerShell 为每个区域创建一个 table,然后在脚本而不是 Snowflake 中处理数据转换,然后将清理后的数据插入 Snowflake。有人有什么想法或建议吗?

问题不在于点几乎相同。这是点 #5 的 x 值低于点 #6,这是一条非法路径。如果它与最终 x 值完全相同或更高,它就可以工作。

假设它只是小数点后第 13 位的舍入问题,并且这些点的顺序正确,否则您可以使用 regexp_replace 截断一位(或多位)小数以使其正常工作。

select
    'MULTIPOLYGON ((( -103.13610284560149 32.725882872864453 , -103.14470012813675 32.725738931539986 , -103.14475163540753 32.732599004640321 , -103.13626891853778 32.732448970077257 , -103.1361028456015 32.725882872864453 , -103.13610284560149 32.725882872864453)))' as value,
    to_geography(regexp_replace(value, '[0-9]{1}([^\d\.])', '\1'))