第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さんから以下の投稿がありました!
実際に試してみました!
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