【问题标题】:Object conversion with JavaScript UDF in Snowflake (floats)在 Snowflake(浮点数)中使用 JavaScript UDF 进行对象转换
【发布时间】:2021-04-20 22:50:27
【问题描述】:

考虑一下 Snowflake 中的以下 JavaScript UDF:

create or replace function PUBLIC.TEST(F FLOAT)
    returns VARIANT
    language JAVASCRIPT
    returns NULL on NULL INPUT
    immutable
    comment = 'Test.'
as
    $$
        try {
            return F;
        } catch (err) {
            return err;
        }
    $$
;

此函数接收 FLOAT 值并将其作为 VARIANT 返回。例如,

select PUBLIC.TEST(-73.60738);

返回

-7.360738000000001e+01

不错,但我必须承认我对指数表示法和浮点算术有点恼火,特别是因为返回浮点数的类似函数会返回接收到的值。而且这样的结果与简单的SQL语句如

是不一致的

select -73.60738::VARIANT;

返回

-73.60738

显然,这样的函数非常无用,但我在尝试找出与实际用例类似的烦恼的原因时编写了它,即反转给定几何图形顶点在 GEOGRAPHY 值中的顺序。对于我的真实用例,我开发了一个函数(ST_REVERSE),它接收一个 GEOGRAPHY 作为参数并使用简单的数组操作反转其几何顶点的顺序(如果有人感兴趣,我可以转发代码)但我不知何故当我看到它时感到很失望

select PUBLIC.ST_REVERSE(TO_GEOGRAPHY('LINESTRING (-73.60746 45.52045, -73.60744 45.52050, -73.60738 45.52053, -73.60730 45.52056, -73.60718 45.52058, -73.60708 45.52059)'))

返回

{
  "coordinates": [
    [
      -7.360708000000000e+01,
      4.552059000000000e+01
    ],
    [
      -7.360718000000000e+01,
      4.552058000000000e+01
    ],
    [
      -7.360730000000000e+01,
      4.552056000000000e+01
    ],
    [
      -7.360738000000001e+01,
      4.552053000000000e+01
    ],
    [
      -7.360744000000000e+01,
      4.552050000000000e+01
    ],
    [
      -7.360746000000000e+01,
      4.552045000000000e+01
    ]
  ],
  "type": "LineString"
}

这种行为使测试和验证对人眼来说更具挑战性,但更重要的是,它大大增加了以 GeoJSON 格式导出到下游的数据大小。

这样的结果是预期的吗?谁能提供解释和/或一些解决方法?

【问题讨论】:

    标签: javascript floating-point user-defined-functions snowflake-cloud-data-platform


    【解决方案1】:

    这更多是针对您的特定问题的解决方法,而不是一般修复。您的坐标似乎有 6 个小数位。您可以使用 JavaScript number.toFixed() 函数。

    create or replace function PUBLIC.TEST(F FLOAT)
        returns VARIANT
        language JAVASCRIPT
        returns NULL on NULL INPUT
        immutable
        comment = 'Test.'
    as
        $$
            try {
                return F.toFixed(6);
            } catch (err) {
                return err;
            }
        $$
    ;
    

    这可能会产生一些小问题,您应该能够解决这些问题。例如,函数的输出是双引号。对于具有坐标 JSON 的较大函数,这应该是可修复的。这些数字也将有尾随零,在 JSON 中应该被读取它们的任何内容忽略。

    【讨论】:

    • 感谢您的回复。是的,作为一种解决方法,我想得一样多。对于我的测试用例,我可以轻松添加一个 TEST_SQL SQL UDF,它调用您的 JavaScript UDF(或我的),例如 PUBLIC.TEST(F)::FLOAT:输入值按最初输入/显示的方式返回。然而,对于我的实际用例,即反转几何中顶点的顺序,事情变得有点丑陋,更不用说更复杂了。我会再考虑一下。问候。
    • 其实,忘记使用额外的UDF。 PUBLIC.TEST JavaScript UDF 的两个版本,无论是我的还是你的使用 toFixed(),如果转换为 FLOAT,都会产生相同的结果,例如,select TEST.PUBLIC( -73.60738)::FLOAT:-73.60738。考虑到这一点,我意识到 Snowflake 似乎 1)在纬度和经度上处理多达 9 个有效小数,以及 2)在其 WKT 几何表示中删除非有效小数。是的,据我所知,select TO_GEOGRAPHY(ST_ASWKT(PUBLIC.ST_REVERSE(geom))) 之类的东西返回了预期的结果,尽管对性能的影响很小。
    猜你喜欢
    • 2021-09-30
    • 1970-01-01
    • 2011-06-30
    • 2021-08-11
    • 2019-10-01
    • 2013-07-16
    • 2021-05-24
    • 2021-06-18
    • 1970-01-01
    相关资源
    最近更新 更多