【问题标题】:bigquery hex string to bytes/intbigquery 十六进制字符串到字节/整数
【发布时间】:2018-03-21 17:52:45
【问题描述】:

是否有可能将由两个字节组成的十六进制字符串转换为字节/整数,而第一个字节是 lsb,第二个是 msb。

处理后:

#standardSQL
SELECT
  timestamp, CAN_Frame, bytes,
  STRING_AGG(CASE WHEN f='83' AND p IN (5, 6) THEN b ELSE '' END, ' ' ORDER BY p) AS Aiout,
  STRING_AGG(CASE WHEN (f='83' AND p=7) OR (f='84' AND p=2)  THEN b ELSE '' END, ' ' ORDER BY p) AS Biout, 
  STRING_AGG(CASE WHEN f='84' AND p IN (3, 4) THEN b ELSE '' END, ' ' ORDER BY p) AS Avout,
  STRING_AGG(CASE WHEN f='84' AND p IN (5, 6) THEN b ELSE '' END, ' ' ORDER BY p) AS Bvout
FROM (
  SELECT timestamp, CAN_Frame, TRIM(SPLIT(CAN_Frame)[OFFSET(4)]) AS bytes, 
SUBSTR(TRIM(SPLIT(CAN_Frame)[OFFSET(4)]), 1, 2) AS f 
  FROM `data.source`
  WHERE SUBSTR(TRIM(SPLIT(CAN_Frame)[OFFSET(4)]), 1, 2) IN ('83', '84')
), UNNEST(SPLIT(bytes, ' ')) AS b WITH OFFSET AS p
GROUP BY timestamp,CAN_Frame, bytes 
ORDER BY timestamp desc

(感谢 Mikhail Berlyant)

我有 4 列(aiout、biout、avout、bvout),每列由十六进制字符串中的两个字节组成,如下所示:

       Aiout    Biout  Avout    Bvout
                 00    25 00    21 00 
       03 00      0D                   
                  00   27 00    08 00 
                 00    1C 00    15 00 
                 00    25 00    21 00 
       03 00      03                   
                  00   2A 00    26 00 
       03 00      0D                   
       00 00      07                   
       04 00      04                   

使用强制转换、格式、整数等函数...我总是遇到内部错误,请求无法完成。

最好的问候

【问题讨论】:

  • 如果您遇到内部错误,请在 issue tracker 上提交带有作业 ID 的错误报告,以便有人可以查看。

标签: sql string int hex google-bigquery


【解决方案1】:

这是一个基于Mikhail's answer to your previous question 的示例。它采用空格分隔的字节并将它们转换为前缀为 0x 的字符串,没有可以转换为 int64 的空格:

#standardSQL
CREATE TEMP FUNCTION HexToInt(hex_string STRING) AS (
  IFNULL(SAFE_CAST(CONCAT('0x', REPLACE(hex_string, ' ', '')) AS INT64), 0)
);

WITH `data.source` AS (
  SELECT 'S,0,2B3,8, C2 B3 00 00 00 00 03 DE' AS frame UNION ALL
  SELECT 'S,0,3FA,6, 00 E0 04 A5 00 0B' UNION ALL
  SELECT 'S,0,440,8, 83 40 4E A5 00 47 00 64' UNION ALL
  SELECT 'S,0,450,8, 84 50 01 12 01 19 01 B3' UNION ALL
  SELECT 'S,0,4B0,8, 84 B0 4E A5 00 43 00 64' 
)
SELECT *,
  HexToInt(Aiout) AS Aiout_int64,
  HexToInt(Biout) AS Biout_int64,
  HexToInt(Avout) AS Avout_int64,
  HexToInt(Bvout) AS Bvout_int64
FROM (
  SELECT
    frame, bytes,
    STRING_AGG(CASE WHEN f='83' AND p IN (5, 6) THEN b ELSE '' END, ' ' ORDER BY p) AS Aiout,
    STRING_AGG(CASE WHEN (f='83' AND p=7) OR (f='84' AND p=2)  THEN b ELSE '' END, ' ' ORDER BY p) AS Biout,
    STRING_AGG(CASE WHEN f='84' AND p IN (3, 4) THEN b ELSE '' END, ' ' ORDER BY p) AS Avout,
    STRING_AGG(CASE WHEN f='84' AND p IN (5, 6) THEN b ELSE '' END, ' ' ORDER BY p) AS Bvout
  FROM (
    SELECT frame, TRIM(SPLIT(frame)[OFFSET(4)]) AS bytes, SUBSTR(TRIM(SPLIT(frame)[OFFSET(4)]), 1, 2) AS f
    FROM `data.source`
    WHERE SUBSTR(TRIM(SPLIT(frame)[OFFSET(4)]), 1, 2) IN ('83', '84')
  ), UNNEST(SPLIT(bytes, ' ')) AS b WITH OFFSET AS p
  GROUP BY frame, bytes
  ORDER BY frame
);

输出如下:

+------------------------------------+-------------------------+-------------+-----------+-------------+-------------+-------------+-------------+-------------+-------------+
|               frame                |          bytes          |    Aiout    |   Biout   |    Avout    |    Bvout    | Aiout_int64 | Biout_int64 | Avout_int64 | Bvout_int64 |
+------------------------------------+-------------------------+-------------+-----------+-------------+-------------+-------------+-------------+-------------+-------------+
| S,0,440,8, 83 40 4E A5 00 47 00 64 | 83 40 4E A5 00 47 00 64 |      47 00  |        64 |             |             |       18176 |         100 |           0 |           0 |
| S,0,450,8, 84 50 01 12 01 19 01 B3 | 84 50 01 12 01 19 01 B3 |             |   01      |    12 01    |      19 01  |           0 |           1 |        4609 |        6401 |
| S,0,4B0,8, 84 B0 4E A5 00 43 00 64 | 84 B0 4E A5 00 43 00 64 |             |   4E      |    A5 00    |      43 00  |           0 |          78 |       42240 |       17152 |
+------------------------------------+-------------------------+-------------+-----------+-------------+-------------+-------------+-------------+-------------+-------------+

编辑:如果你想改变解释字节的顺序,你可以在转换之前反转内容,例如:

#standardSQL
CREATE TEMP FUNCTION HexReverse(hex_string STRING) AS (
  (SELECT STRING_AGG(s, ' ' ORDER BY off DESC)
   FROM UNNEST(SPLIT(hex_string, ' ')) AS s WITH OFFSET off)
);

CREATE TEMP FUNCTION HexToInt(hex_string STRING) AS (
  IFNULL(SAFE_CAST(CONCAT('0x', REPLACE(HexReverse(hex_string), ' ', '')) AS INT64), 0)
);

WITH `data.source` AS (
  SELECT 'S,0,2B3,8, C2 B3 00 00 00 00 03 DE' AS frame UNION ALL
  SELECT 'S,0,3FA,6, 00 E0 04 A5 00 0B' UNION ALL
  SELECT 'S,0,440,8, 83 40 4E A5 00 47 00 64' UNION ALL
  SELECT 'S,0,450,8, 84 50 01 12 01 19 01 B3' UNION ALL
  SELECT 'S,0,4B0,8, 84 B0 4E A5 00 43 00 64' 
)
SELECT *,
  HexToInt(Aiout) AS Aiout_int64,
  HexToInt(Biout) AS Biout_int64,
  HexToInt(Avout) AS Avout_int64,
  HexToInt(Bvout) AS Bvout_int64
FROM (
  SELECT
    frame, bytes,
    STRING_AGG(CASE WHEN f='83' AND p IN (5, 6) THEN b ELSE '' END, ' ' ORDER BY p) AS Aiout,
    STRING_AGG(CASE WHEN (f='83' AND p=7) OR (f='84' AND p=2)  THEN b ELSE '' END, ' ' ORDER BY p) AS Biout,
    STRING_AGG(CASE WHEN f='84' AND p IN (3, 4) THEN b ELSE '' END, ' ' ORDER BY p) AS Avout,
    STRING_AGG(CASE WHEN f='84' AND p IN (5, 6) THEN b ELSE '' END, ' ' ORDER BY p) AS Bvout
  FROM (
    SELECT frame, TRIM(SPLIT(frame)[OFFSET(4)]) AS bytes, SUBSTR(TRIM(SPLIT(frame)[OFFSET(4)]), 1, 2) AS f
    FROM `data.source`
    WHERE SUBSTR(TRIM(SPLIT(frame)[OFFSET(4)]), 1, 2) IN ('83', '84')
  ), UNNEST(SPLIT(bytes, ' ')) AS b WITH OFFSET AS p
  GROUP BY frame, bytes
  ORDER BY frame
);

【讨论】:

  • 感谢您的解决方案!所以它是用临时函数解决的。问题是字节是小端的。这是我用使用的演示程序 (tableau) 解决的一个问题,但如果知道 bigquery 编程的方法会很高兴
  • 我添加了另一个示例,展示了如何在转换为 int64 之前反转 HexToInt 中的字节。
猜你喜欢
  • 2015-08-08
  • 2017-08-07
  • 1970-01-01
  • 2013-08-09
  • 2013-10-13
  • 1970-01-01
  • 2014-05-26
  • 2015-01-17
相关资源
最近更新 更多