ある値に最も近い値を BigQuery のテーブルから取得するGAS

前提

・ある数値に最も近い値を別のテーブルから取得したい
・取得対象のテーブルは BigQuery に存在する
・今回はある数値よりも小さい数値しか考えない(仮に大きい数字があったとしても同じような方法で対応可能)

スクリーンショット 2021-03-18 22.02.58

実装

行・列のインデックスは各自のシートに合わせて変更すること。

function calcApproximation() {
 //プロジェクトID設定
 const projectId = 'プロジェクトID';
 //スプレッドシートの設定
 //近似値を求める値リストのシートをシート名称から取得
 const ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("value_list");
 //出力シートのインスタンス作成。今回はValue List の横に値を出力する
 const result_sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("value_list");
 //Settingsシートから計算範囲を取得
 const setting_sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Settings");
 var start_row = setting_sheet.getRange("B1").getValue();
 var end_row = setting_sheet.getRange("B2").getValue();
 // start_row ~ end_row の範囲のデータを取得
 // end_row がnullの場合は最下部まで。start_row がnullの場合のエラー処理などは割愛
 if(end_row == ""){
   var data = ss.getRange(start_row, 3, ss.getLastRow).getValues();
 }else{
   var data = ss.getRange(start_row, 3, end_row-start_row+1).getValues();
 }
 Logger.log(data);
 Logger.log(data.length);
 //最後にsetRange()で列単位にシートを更新する為の二次元配列の準備
 var nearestScoreArray = [];
 // データの行数分繰り返す(今回はヘッダー行数は考慮しない)
 for(i = 0; i <= data.length-1 ; i++) {
   // 基準値よりも小さく最も近い値を取得するクエリ
   // なお、GAS から BQ API 実行する時はFROM句にプロジェクトIDやバッククォートは不要
   // それと、長いテキスト value を折り返して記載する際にはバックスラッシュ
   var sql = 
   "SELECT score FROM [dataset名称].[テーブル名称]\
    WHERE score <= "
   + data[i] +
   " ORDER BY score DESC LIMIT 1"
   Logger.log(sql)
   // BigQuery API の実行
   let query_results;
   let resource = {
    query : sql,
    timeoutMs: 1000000
   };
   try {
     query_results = BigQuery.Jobs.query(resource, projectId);
   } catch (err) {
     Logger.log(err);
     Browser.msgBox(err);
     return;
   }
   Logger.log(query_results);
   // BigQuery API のレスポンスから Value を取得
   let lower_score = query_results.rows[0].f[0].v;
   Logger.log(lower_score);
   // 最終的に setValues で列ごと更新するために2次元配列にリストの形でpushする
   nearestScoreArray.push([lower_score]);
   Logger.log(nearestScoreArray);
 }
 // 更新範囲の取得
 let updateRange = result_sheet.getRange(start_row,5, end_row-start_row+1)
 // 更新処理
 updateRange.setValues(nearestScoreArray);
}

//起動時のmenu追加
function onOpen() {
 let menus = [{name:'実行',functionName:'calcApproximation'}];
 ss.addMenu('BigQuery',menus);
}

[参考サイト]
GASでBigqueryからデータを取得して分析に活用する

ちなみに、BIgQuery API のレスポンス

BIgQuery API のレスポンスは以下のような形をしている。

{totalRows=1, kind=bigquery#queryResponse, cacheHit=true, jobReference={projectId=[プロジェクトID], location=US, jobId=job_ほげほげほげほげ}, jobComplete=true, rows=[{f=[{v=47201}]}], totalBytesProcessed=0, schema={fields=[{mode=NULLABLE, type=INTEGER, name=score}]}}

この記事が気に入ったらサポートをしてみませんか?