だらだらやるよ。

こげつのIT技術メモ

負数と0に対応した総積を求める方法

ふおっと、突っ込み入っちゃった!
計算で総積を求める際の注意点 - ぐるぐる~

そもそも総積求めたいとか言ってる場合にNULLとかゼロとか入る可能性あるのかなーとか思いつつまぁ適当に。
どうなんですかね?ちなみに僕は今まで業務で総積もとめるケースに当たったことないのでわかりません。


というわけで修正版。

SELECT
   exp(sum(case when n <> 0 then ln(abs(n)) else 1 end))--ゼロ以外を処理
   *(case when sum(case when n<0 then 1 else 0 end)%2=0 then 1 else
-1 end)--負数ならマイナス1をかける
   *(case when sum(case when n=0 or n is null then 1 else 0 end)>0 then 0 else 1
end)--ゼロかNULLが含まれてたら無理やりゼロに
FROM
   (
   SELECT 1 as id, 1 as n
   UNION ALL SELECT 1, 2
   UNION ALL SELECT 1, 3
   UNION ALL SELECT 1, 0

   UNION ALL SELECT 2, 1
   UNION ALL SELECT 2, -2
   UNION ALL SELECT 2, -3

   UNION ALL SELECT 3, 1
   UNION ALL SELECT 3, -2
   UNION ALL SELECT 3, 3

   ) as nums
GROUP BY id
ORDER BY id

こんな感じで自分の書き方でやってみた。
0が含まれてたら最後にゼロ掛けて無理やり結果を0にしてるのが意図がわかりにくいのと、無駄な演算が行われているのがダメですね。
ただ個人的には参照先のSQLよりも読みやすいと感じます。


これはすごく個人的な感覚なのですが、
僕はSQLを書くときに、テーブルが結果になるのを視覚的に考えてます。
で、そのイメージの中でSELECT句内の関数の実行のタイミングって、集計前、集計、集計後の3回しかなくて、
その中で値が次々に置き換わったり集計されたりっていうのを想像しているのですが、
集計結果によって分岐して、集計するかどうかを決めるっていうのは個人的に違和感があるんですよね。
なのでまぁ今回のようにそれぞれの集計結果を掛け算する形になりました。


どうなんだろう、みんなSQLってどうやってイメージして書いているんだろうか。
ちなみに普通のプログラムを書くときはオブジェクトが適当な塊になってて、メッセージをとばしたりってのがぼんやりと頭の中に出てきてたりします。
あとループだとなんかよくわかんないけどすげー回ってたりとか。


とまぁここまで書いておいてあれですが
ユーザー定義関数が使えるのであれば作ったほうがいいんじゃないんですかね。
誤差の問題もあるし。
ポスグレは作れるっぽいことがマニュアルに書いて有りましたけど詳細は不明です。つくったことないし。