2017-10-10 110 views
1

是否有可能將由兩個字節組成的十六進制字符串轉換爲字節/ int,而第一個字節是lsb,第二個是msb。bigquery十六進制字符串到字節/ int

後處理該:

#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 

我已經與在十六進制串中的每個由兩個字節組成了4列(aiout,biout,AVOUT,bvout)(由於米哈伊爾Berlyant)看起來像這樣:

 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     

與像cast,格式,整數,...我總是有一個內部錯誤和請求無法完成。

問候

+0

如果你得到一個內部錯誤,請提交一個錯誤報告,在[issue跟蹤器](https://issuetracker.google.com/issues?q=componentid:187149%2B),以便有人可以查看它。 –

回答

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 
); 
+0

感謝您的解決方案!所以它是通過臨時功能解決的。問題是這些字節是小尾數。這是一個問題,我解決了使用演示程序(畫面),但它會很高興知道bigquery編程的一種方式 – scotti

+0

我添加了另一個例子,顯示如何在轉換爲int64之前反轉HexToInt中的字節。 –