0
0

Athenaでdouble型(実数型)を取得したら指数表記になってたので変換した話

Last updated at Posted at 2024-06-25

はじめに

LambdaとAthenaを使ってデータを取得、返却するプログラムを作りテストをしたところ「0.0003」などの小数が「3.0E-4」などの指数表記で帰ってきていました。
1つのLambdaで指定したテーブルの全列を取得できるような仕様にしており、特定の列をCASTするといったアプローチは取れなかったため指定されたテーブルのスキーマーをもとに取得列を動的に作成するLambdaを作成しました。

本題

main.py

import json
import awswrangler as wr

DATABASE = 'database_name'
TABLE_NAME = 'table_name'
OUTPUT_LOCATION='s3://example'

    
def lambda_handler(event, context):
 
  try:

    # テーブルの列名、型を取得
    query = f"""
        select 
            * 
        from information_schema.columns 
        where LOWER(table_name) = LOWER('{TABLE_NAME}')
        ;
    """
    df = wr.athena.read_sql_query(sql=query, database=DATABASE, s3_output=OUTPUT_LOCATION)

    # 型がdoubleの時はdecimalにcastする(decimalにすると指数表記じゃなくなる)
    str_columns = ""
    for index, row in df.iterrows():
      str_columns += f"cast({row["column_name"]} as decimal(38,10)) as {row["column_name"]}" if row["data_type"] == "double" else row["column_name"]
      str_columns += ","
    str_columns = str_columns[:-1] # 最後のカンマを削除
    
    
    query = f"""
        select
        {str_columns}
      from {TABLE_NAME}
        ;
    """
    df = wr.athena.read_sql_query(sql=query, database=DATABASE, s3_output=OUTPUT_LOCATION)
    response = {"data":json.loads(df.to_json(orient='records'))}
    return {
      'statusCode':200,
      'body': json.dumps(response)
    }
    
  except Exception as e:
    print(e)
    return {
      'statusCode': 500,
      'body': json.dumps({ 'error': 'faild' }),
    }

おわり

今回は全てのテーブルで同じように動作させるためにこのような手段を取りましたが本来はあまり使わなそうな手段だと思います。
ですが、同じような悩みがあるかたの参考にしていただければ嬉しいです。

そして、この記事を書きながら思いました。
修正前はboto3でathenaを実行して結果をそのまま出力していましたが、今回はawswranglerを使っているのでうまいこと変換してくれていないかと。
忘れていなければ確認してみようと思います。

追記

やはりawsranglerの場合0.003の形で表示されていました...

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0