2017-01-12 8 views
3

私はこのトピックについて多分検索できませんでした。私はApacheのロギング情報を取得するテーブルProtopayload.resourceを持っています。その結果、私が興味を持っているフィールドには、検索する必要がある複数の値が含まれています。フィールドはPHPのURLスタイルでフォーマットされています。 すなわちビッグ・クエリでフィールドを分割する

/?id=13242134123&ver=12&os_bits=64&os_type=mac&lng=EN 

これは、すべての検索がデータを取得するために、本当に長い正規表現で終わることができます。次に、ステートメントを結合してデータを結合します。私が考えていた何MAC /勝つ統計

SELECT 
    t1.date, t1.wincount, COALESCE(t2.maccount, 0) AS maccount 
FROM (
    SELECT 
    DATE(metadata.timestamp) AS date, 
    INTEGER(COUNT(protoPayload.resource)) AS wincount 
    FROM (TABLE_DATE_RANGE(tablename, DATE_ADD(CURRENT_TIMESTAMP(), -30, 'DAY'), CURRENT_TIMESTAMP())) 
    WHERE 
    (REGEXP_MATCH(protoPayload.resource, r'ver=[11,12')) 
    AND protoPayload.resource CONTAINS 'os=win' GROUP BY date) t1 
LEFT JOIN (
    SELECT 
    DATE(metadata.timestamp) AS date, 
    INTEGER(COUNT(protoPayload.resource)) AS maccount 
    FROM (TABLE_DATE_RANGE(tablename, DATE_ADD(CURRENT_TIMESTAMP(), -30, 'DAY'), CURRENT_TIMESTAMP())) 
    WHERE 
    (REGEXP_MATCH(protoPayload.resource, r'cv=[p,m][17,16,15,14]')) 
    AND protoPayload.resource CONTAINS 'os=mac' GROUP BY date) t2 
ON 
    t1.date = t2.date 
ORDER BY t1.date 

を組み合わせること

例の検索では、類似した正規表現検索を使用することでした。新しいテーブルを作成します。その後、関係フィールドを持つ新しいテーブルにデータを保存します。将来のロギングを修正して、テーブルに正しくログするようにします。

私の質問はこの有効な解決策ですか、それともGoogle BigQueryでこれを達成するための簡単な方法がありますか?データを変換するより良い方法はありますか? 入力してくれてありがとう!

+0

ようこそStackOverflow!ですから、本質的にあなたの質問は、Google BigQueryがURLを簡単に解析できるかどうかです。私はGBQの専門家ではありませんが、一般的に私はあなたのアプローチがうまくいっていると言います。それは、あなたが「どちらが良いですか:aまたはb?」という代替語句をあなたに提供するならば、あなたは答えを得る可能性が高いと思います。 – akousmata

答えて

1

柔軟性を最大限に高めるために、常にJavaScriptのUDFを使用できます。純粋なSQLソリューションよりも処理速度が遅くなりますが、その限界を回避することができます。例えば

:あなたは、一般的にJavaScriptを使用してより速くなり、配列の中にキーと値のペアを解析するためにSQL関数を使用することができます

#standardSQL 
CREATE TEMPORARY FUNCTION parse(query STRING) 
RETURNS STRUCT<id STRING, ver STRING, os_bits STRING, os_type STRING, lng STRING> 
LANGUAGE js AS """ 
    function parseQueryString(query) { 
     // http://codereview.stackexchange.com/a/10396 
     var map = {}; 
     query.replace(/([^&=]+)=?([^&]*)(?:&+|$)/g, function(match, key, value) { 
      (map[key] = map[key] || []).push(value); 
     }); 
     return map; 
    } 

    return parseQueryString(query) 

"""; 


WITH urls AS 
    (SELECT 'id=13242134123&ver=12&os_bits=64&os_type=mac&lng=EN' query 
    UNION ALL 
    SELECT 'id=13242134124&ver=12&os_bits=64&os_type=mac&lng=EN1&lng=EN2' query 
) 


SELECT query, parse(query) as parsed 
FROM urls;. 

enter image description here

2

。例えば、

#standardSQL 
CREATE TEMPORARY FUNCTION ParseKeys(queryString STRING) 
RETURNS ARRAY<STRUCT<key STRING, value STRING>> AS (
    (SELECT 
    ARRAY_AGG(STRUCT(
     entry[OFFSET(0)] AS key, 
     entry[OFFSET(1)] AS value)) 
    FROM (
    SELECT SPLIT(pairString, '=') AS entry 
    FROM UNNEST(SPLIT(REGEXP_EXTRACT(queryString, r'/\?(.*)'), '&')) AS pairString) 
    ) 
); 
SELECT ParseKeys('/?foo=bar&baz=2'); 

あなたは構造体のフィールドにキーを旋回させる機能で、この上に構築することができます一緒にすべてを置く

#standardSQL 
CREATE TEMP FUNCTION GetAttributes(queryString STRING) AS (
    (SELECT AS STRUCT 
    MAX(IF(key = 'id', CAST(value AS INT64), NULL)) AS id, 
    MAX(IF(key = 'ver', CAST(value AS INT64), NULL)) AS ver, 
    MAX(IF(key = 'os_bits', CAST(value AS INT64), NULL)) AS os_bits, 
    MAX(IF(key = 'os_type', value, NULL)) AS os_type, 
    MAX(IF(key = 'lng', value, NULL)) AS lng 
    FROM UNNEST(ParseKeys(queryString))) 
); 

、あなたはいくつかのサンプル入力でGetAttributes機能を試すことができます。正規表現は正しくないと意志のnのよう

#standardSQL 
CREATE TEMPORARY FUNCTION ParseKeys(queryString STRING) 
RETURNS ARRAY<STRUCT<key STRING, value STRING>> AS (
    (SELECT 
    ARRAY_AGG(STRUCT(
     entry[OFFSET(0)] AS key, 
     entry[OFFSET(1)] AS value)) 
    FROM (
    SELECT SPLIT(pairString, '=') AS entry 
    FROM UNNEST(SPLIT(REGEXP_EXTRACT(queryString, r'/\?(.*)'), '&')) AS pairString) 
    ) 
); 
CREATE TEMP FUNCTION GetAttributes(queryString STRING) AS (
    (SELECT AS STRUCT 
    MAX(IF(key = 'id', CAST(value AS INT64), NULL)) AS id, 
    MAX(IF(key = 'ver', CAST(value AS INT64), NULL)) AS ver, 
    MAX(IF(key = 'os_bits', CAST(value AS INT64), NULL)) AS os_bits, 
    MAX(IF(key = 'os_type', value, NULL)) AS os_type, 
    MAX(IF(key = 'lng', value, NULL)) AS lng 
    FROM UNNEST(ParseKeys(queryString))) 
); 
SELECT url, GetAttributes(url).* 
FROM UNNEST(['/?id=13242134123&ver=12&os_bits=64&os_type=mac&lng=EN', 
      '/?id=2343645745&ver=15&os_bits=32&os_type=linux&lng=FR']) AS url; 
0

私はあなたの質問に
1.ルックスをクエリ内のいくつかの問題を参照してくださいあなたは
2.クエリが過剰設計重くし、

以下

非常に簡素化することができる何を期待OTキャプチャがポイント

SELECT 
    DATE(metadata.timestamp) AS date, 
    SUM(REGEXP_MATCH(protoPayload.resource, r'ver=(11|12)\b') 
     AND protoPayload.resource CONTAINS 'os_type=win' 
) AS wincount, 
    SUM(REGEXP_MATCH(protoPayload.resource, r'cv=(p|m)(17|16|15|14)\b') 
     AND protoPayload.resource CONTAINS 'os_type=mac' 
) AS maccount 
FROM (TABLE_DATE_RANGE(tablename, DATE_ADD(CURRENT_TIMESTAMP(), -30, 'DAY'), 
            CURRENT_TIMESTAMP())) 
GROUP BY date 

上記のアドレスにあることに注意してください:あなたは質問に問い合わせるBigQueryのレガシーSQLで書かれています私は同じ方言で私の答えを保ちます

関連する問題