2017-10-10 18 views
1

2バイトからなる16進文字列をバイト/ intに変換する可能性がありますが、最初のバイトはlsbで、2番目のバイトはmsbです。これを処理した後bigquery 16進文字列をバイト/ 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 

(ミハイルBerlyantのおかげ)

iは各16進文字列に2バイトで構成されると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     

キャスト、フォーマット、整数などの機能を備えています...私は常に内部エラーがあり、要求を完了できませんでした。

よろしくここ

+0

内部エラーが発生した場合は、[issueトラッカー](https://issuetracker.google.com/issues?q=componentid:187149%2B)を参照してください。 –

答えて

1

Mikhail's answer to your previous question上に構築例です。これは、スペースで区切られたバイトを取り、int64型にキャストすることができ、スペースなしで0x前に付加文字列にそれらを回す:

#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

このソリューションをお寄せいただきありがとうございます!テンポリー機能で解決しました。問題は、バイトがリトルエンディアンであることです。それは私が使用したプレゼンテーションプログラム(tableau)で解決した問題ですが、bigqueryプログラミングの方法を知っているといいです。 – scotti

+0

int64にキャストする前に 'HexToInt'のバイトをどうやって逆転できるかを示す別の例を追加しました。 –

関連する問題