bigquery十六进制字符串到bytes / int

时间:2017-10-10 10:45:10

标签: sql string int hex google-bigquery

是否有可能将由两个字节组成的十六进制字符串转换为bytes / int,而第一个字节是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                   

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

最好的问候

1 个答案:

答案 0 :(得分: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
);