🔥

第3回Snowflake Rookies Camp ~FrostyFriday week5の振り返り〜

に公開

Snowflake Rookies Camp 幹事メンバーのhueです。
この記事は2025年6月13日2025年6月18日に開催した
「第3回Snowflake Rookies Camp~初心者向け勉強会~」の内容を振り返ります。

新幹事2名

改めて、当日参加いただいた皆さん、ありがとうございます!!
今回から新たに幹事2名を紹介します!
当日ハンズオンの内容を解説してくれた、Hirokiさん
ハンズオンを実施してくれた唐内さん
みなさん、よろしくお願いします!

Frosty Friday week5

当日はこちらの記事にて紹介しているクエリを実行しました。
ぜひ振り返りいただければと思います。

UDF

今回Rookies Campの特別問題でBMIを計算!
ご案内したUDFでPythonとSQLで返ってくる値に違いがありました。

Python

create or replace function calc_bmi_python(height number, weight number)
returns number
language python
runtime_version = '3.12'
handler = 'calc_bmi'
as
$$
def calc_bmi(height,weight):
    return weight / ((height/100)** 2)
$$
;

SQL

create or replace function calc_bmi_sql(height number, weight number)
returns number
language sql
as
$$
weight / ((height / 100)*(height / 100))
$$;

両方の結果を横に並べて確認!!

select height,weight,calc_bmi_python(height,weight)as BMI_py, calc_bmi_sql(height,weight)as BMI_sql
from table_week5_bmi;

以下のようにPythonは整数、SQLは小数点以下の数字を含む形で返ってきました。

なんで???

検証

Python

UDFの2行目のreturnsを「number」から「float」に変更して実行します

create or replace function calc_bmi_python(height number, weight number)
returns float
language python
runtime_version = '3.12'
handler = 'calc_bmi'
as
$$
def calc_bmi(height,weight):
    return weight / ((height/100)** 2)
$$
;

先ほど同じコードで結果を比較します。

Pythonも小数点を含む値が返ってきました!

1回目の勉強会の後Aokkyさんから以下の投稿がありました!

https://x.com/powerofmusic777/status/1933553307571945821

実際に試してみました!

returns number(38,10)に変更して

create or replace function calc_bmi_python(height number, weight number)
returns number(38,10)
language python
runtime_version = '3.12'
handler = 'calc_bmi'
as
$$
def calc_bmi(height,weight):
    return weight / ((height/100)** 2)
$$
;

小数点以下の数字も返してくれました。

ChatGPTに聞いてみた

2回目の際、ChatGPTに聞いていただいた方がいました。
…思わず私も聞いちゃいましたので共有します。

Python UDF の戻り値が整数(例:35, 30, 23)になっているのは、returns number の指定が「戻り値の型を制限している」のではなく、「Python内での演算結果が整数として返されている」からです。

違いの原因

1. Python UDFでは戻り値が暗黙的に整数に変換された

Python の return の結果が 浮動小数点数(例:35.456448)でも、number 型にマッピングされたときに Snowflake 側で丸め処理が入ってしまうことがあるのが原因です。

特に、Python の float を returns number で返すと、Snowflake 側が NUMBER(38, 0)(小数部0桁の整数)として受け取ってしまう可能性があります。

2. SQL UDF はそのまま精度を保って返している

SQL UDF は number を使っても、式の評価結果の小数部もそのまま保ちます(通常、NUMBER(38, 18) などの高精度型が使われる)。

Hirokiさんが調べてくれた!

今回から幹事に加わってくれたHirokiさんがtypeを調べてくれたので共有します!

Python

returnsが「returns VARCHAR」
Pythonの中のreturnが「return type(weight / ((height/100)** 2))」

create or replace function calc_bmi_python(height number, weight number)
returns VARCHAR
language python
runtime_version = '3.12'
handler = 'calc_bmi'
as
$$
def calc_bmi(height,weight):
    return type(weight / ((height/100)** 2))
$$
;

SQL

returnsが「returns VARCHAR」
Pythonの中のreturnが「typeof(weight / ((height / 100)*(height / 100)))」

create or replace function calc_bmi_sql(height number, weight number)
returns VARCHAR
language sql
as
$$
typeof(weight / ((height / 100)*(height / 100)))
$$;

実行結果


type・typeofで型を見てみると、pythonはfloat・sqlはdecimalになってました。
flaotはnumberにキャストされるので丸められる、decimalはnumberと同義語なのでキャストされないということだと!!

小数点以下の数字も含めて値を返して欲しい場合の対処

項目 Python UDF SQL UDF
デフォルトの戻り型 number → 整数(小数なし)になる number → 小数保持される
原因 Python の float が number(38,0) にマッピング SQL 側は式の結果をそのまま保持
解決法 returns float または returns number(10,5) などで明示 特に不要

これで振り返りは以上となります!!
今回もご参加いただきありがとうございました!
UDFで関数作って終わるかと思いきや、オリジナル問題からちょっとした仕様が疑問に!
思いもよらない形でまとめに辿り着きました!
引き続き勉強会を通じてSnowflakeへの理解を深めていければと思います。

次回もよろしくお願いします✨

Discussion