BigQuery - 将十六进制字符串转换为 NUMERIC 或 BIGNUMERIC?

问题描述 投票:0回答:2

我有一个十六进制格式的数据字符串。类似的东西

'0x00000000000000000000000000000000000000000000000000000000000000006cc09155dd769741d7cd1c6a3334a1aeef62da2d0e92a39230becd6e56c2ad490000000000000000000000000000000000000000000000007ce66c50e2840000' as data

我知道

substring(data, 131)
是一个很大的数字。

对于较小的数字我可以很好地通过

SAFE_CAST(CONCAT('0x', SUBSTRING(data, 131)) AS INT64)

SAFE_CAST(CONCAT('0x', SUBSTRING(data, 131)) AS NUMERIC)
(或大数字)不起作用。

我尝试了类似

FROM_HEX(SUBSTRING(data, 131))
的方法来获取字节格式。但也找不到任何让
BYTE
NUMERIC
的好选择。

sql google-bigquery type-conversion
2个回答
0
投票

对于这么大的数字,甚至

BIGNUMERIC
都无法容纳它们,所以你必须作为字符串来工作。常规 BigQUery 函数将无法处理这些数字,因此我建议您使用
UDF
:

CREATE TEMP FUNCTION from_hex_to_intstring(hex STRING)
RETURNS STRING   
LANGUAGE js AS r"""
    yourNumber = BigInt(hex,16);
    return yourNumber;
  """;

select from_hex_to_intstring('0x00000000000000000000000000000000000000000000000000000000000000006cc09155dd769741d7cd1c6a3334a1aeef62da2d0e92a39230becd6e56c2ad490000000000000000000000000000000000000000000000007ce66c50e2840000') data;
select  from_hex_to_intstring('0x00000000000000000000000000000000000000000009ed194db19b238c000000') data

结果:

-------------------------------
Row | data  
1   | 5695815805094697319662327076913960577653781492348607706655047793592681546373383993595483025021696631917691807178407718241565809060633202962632700189736960
-------------------------------
Row | data  
1   | 12000000000000000000000000
-------------------------------

奖励1: 如果十六进制不是那么大,您可以将其返回为

NUMERIC
BIGNUMERIC

select cast(from_hex_to_intstring(<hex string>) as NUMERIC)

奖励2: 如果您想修剪十六进制上的零,请使用以下(但上面的功能不需要)

select concat("0x",ltrim('0x00000000000000000000000000000000000000000009ed194db19b238c000000',"0x")) as data
-------------------------------
Row | data  
1   | 0x9ed194db19b238c000000
-------------------------------
  • 我建议您仅使用字符串,而不是转换为数字。

0
投票

对于那些来这里寻找答案但无法使用 UDF 因为他们想在物化视图中包含此逻辑的人来说,以下可能是一个解决方案。对于那些也使用 EVM 数据并且还需要应用

decimals
值的人,我们可以通过在计算过程中应用小数位来将更大的值放入 BIGNUMERIC 数据类型中。

我知道它的可读性不太好,但我们正在 BigQuery 的限制范围内工作。

SQL:

WITH input AS (
    SELECT
          '0x0000000000000000000f00a0000a000aaa00c9f78d2893e40000c9f78d2893e4' AS `value`
        , 18 AS decimals
   UNION ALL
   SELECT
          '0x00000000000000000000000000000000000000000009ed194db19b238c000000' AS `value`
        , 0 AS decimals
)
SELECT
    (SELECT SUM(CAST((c << MOD(ARRAY_LENGTH(TO_CODE_POINTS(FROM_HEX(LTRIM(`value`, '0x')))) - 1 - bit, 4) * 8) AS BIGNUMERIC) * (CAST(POWER(2,LEAST(128, FLOOR((ARRAY_LENGTH(TO_CODE_POINTS(FROM_HEX(LTRIM(`value`, '0x'))))- 1 - bit) / 4)*4*8)) AS BIGNUMERIC) / CAST(POWER(10,decimals) AS BIGNUMERIC)) * CAST(POWER(2,GREATEST(0, (FLOOR((ARRAY_LENGTH(TO_CODE_POINTS(FROM_HEX(LTRIM(`value`, '0x'))))- 1 - bit) / 4)*4*8)-128)) AS BIGNUMERIC)) FROM UNNEST(TO_CODE_POINTS(FROM_HEX(LTRIM(`value`, '0x')))) AS c WITH OFFSET bit) AS `value`
FROM
    input

结果:

---------------------------------------------------------------
Row | value
---------------------------------------------------------------
1   | 1436948410046754829959694029135256495.417162625387631588
---------------------------------------------------------------
2   |                               12000000000000000000000000
---------------------------------------------------------------
© www.soinside.com 2019 - 2024. All rights reserved.