2013年10月15日火曜日

プログラムの基本的な作成方法(外部設計編)

週末に他の部署のNewFace君達に聞いてみたらがっくりだったので
プログラム(システム)の基本的な作成方法を記載しておく。

システムとはっ!






たとえ、技術的なことを記述しても所詮は最近のプログラム言語なんて
対話型の言語なんで、文章と同じように章立てして目次を書き、ソレに肉付けしていく方法です。



では話ばかりしていても実践にはなりませんので
友人にエクセルマクロの依頼を受けましたのでこんなVBAとともに送りたいと思います。


■依頼編
友人N:「やぎごん!エクセル得意?」
やぎごん:「んー。グラフとかは得意くないよ」

友人N:「なんか、指定された文字を一気に変換するエクセルシート作ってくんない?」
やぎごん:「ええよ」

↑こんな感じです。

システムの最初なんてだいたい口頭で話を聞きます。
それを折衝 (せっしょう)といいます。

新人のうちはやらないと思いますが、やりたいことを最初から紙に書く(設計書におこす)のはほとんどやりません。会議などでも議題はあってもそこからドンドン膨らませますよね?
私は割りとこの作業が好きです。

ココでのポイントは「できないこと」「やれるけど難しいこと」「できること」を分けることです。

「できないこと」はどうがんばっても出来ないのであきらめてもらうしかないことです。
>プログラムを掛けない人に書けといっても難しいですよね?無理ではないかもしれませんがあまり実現性を感じません。ただし、最初からあきらめてしまうのもいけないのでだいたいは「考えさせてください」とか「かえって上司と相談します」とかで逃げておくのが常套手段です(苦笑)


では「やれるけど難しいこと」はなんでしょうか?
ココでいうと「グラフなどの取り扱い」です。
苦手とか時間がかかるとか、はやりたいことの優先順位(プライオリティ)を聞いてからにしましょう。
コスト面や期限面で見合わない場合はココを切り捨てます。

最後に「出来ること」は、
気持ちよく答えましょう。ただし無理は禁物です。
最近話題のブラック企業などの温床になっているのは日本人の「断れない体質」にもあると思います。
時間や技術面など不安材料があったら上司や同僚などにきちんと相談することが大切です。

ちょっと前に「ほうれんそう(報告・連絡・相談)」は無用であるという記事を読みましたが、
そういう人はたいてい、報告が長い・・・

ので報告は簡潔にするのがお約束です。



では具体的に外部設計に入ります。



■外部設計編
やぎごん:「んじゃさ、具体的にどんなん?」
友人N:「あるセルの中に含まれている文字列を違う文字列に置換して別のセルに表示してほすぃ」


東京都を新宿区って代える感じ?






とこのエクセルを送ってみると

友人N:「あ、こんな感じこんな感じw」
やぎごん:「ちなみにこの変換したい文字列って1つだけ?」
友人N:「んにゃ」(否定の意)
やぎごん:「んじゃ何個位よ?」
友人N:「わかんない。何個かは固定にしないとだめ?」
やぎごん:「いや、別にそういう風に作れなくもないと思う」

というやり取りがあった。

ここでのやり取りは
内部的な変数に格納しておいて変換する
という考えが働いたのです。

↑ここはプログラムを知っている人じゃないと聞けないポイントかもしれませんね。
なのでプログラムを書いたり出来る設計者は後々のやり取りも最小限にとどめられるので個人的にはすべての設計者はプログラマ経験者である必要がある!と個人的には思います。

このやり取りの後にさらにこんなエクセルを送付してみました。









↑コレはあくまで例なのでわかりやすい県庁所在地変換ツールにしてあります。

で、これを別のシートに

という内容を貼り付けて送ったところ

とこのエクセルを送ってみると

やぎごん:「こんな感じ?」
友人N:「そうそう。」
やぎごん:「変換前の文字タマを入れるシートと変換前・後のシートって分かれててもいい?」
友人N:「ええよ。」
やぎごん:「Nよ!変換先のシートの行もフレキシブルなのかい?」
友人N:「そそ。できる?」
やぎごん:「うぃ。むっしゅ~www」
友人N:「めるすぅい~」

という承諾のやり取りが・・・。

これで外部設計が完了です。

要約すると

■やりたいこと
・変換前&変換後を入れる一覧があって、ソレを読み込んで一括返還するシートがほしい

■詳細内容
・変換前&変換後の文字の数がフレキシブル
・変換する文字列の数もフレキシブル
・文字ダマをいれるシートと変換する文字列が入っているシートは別

これが外部設計になります。

こういった内容は「対話」の中で生まれることがほとんどです。
ゆえに設計者にコミュニケーションスキルが求められるのです。

ただ単に相手と話していても設計が決まることも少ないのである程度こちらから選択肢として
提供する必要もあります。

以上で今日のお題はおしまいです。

内部設計~プログラムについてはまた別の機会に話をしたいと思います。

2013年10月10日木曜日

Oracleで年齢算出

昨日のExcel年齢計算に引き続き、
今度はOracleで年齢計算をするSQLを書いてみることにします。

単純に年齢を算出する方法を数学的式で書いてみると・・・

現在の年-生まれた年+1=年齢

ですよね? ちゃんとわかってますよねww
(日本では生まれたときは0歳で、翌年に初めて1歳となるわけなんで・・・)

でもそんな単純なもんではありません。
誕生日を過ぎていないとと1つ年が若い状態です。

たとえば
2014/10/10現在で1973/10/11生まれの人は まだ39歳なわけなので

2014-1973+1≠40歳ではありません。
40代ではないです!まだ30代です。(`・ω・´)キリッ

なんでちゃんと誕生日も加味して計算をしないと怒られます。
特に妙齢の女性は激オコプンです。

ではどうするのか?

Excelの関数では日付差分を求めるDATEIFという関数がありましたが、
Oracleにはあいにく同じ関数はありません。

ただし、似た様な関数でMONTHS_BETWEENと言うものがあります。

使い方はこんな感じです。

MONTHS_BETWEEN(日付1,日付2)

日付1と日付2の差分月を表示します。

ではやってみましょう。


※ちなみに日付1のほうが未来日、日付2に過去日に書かないと結果がマイナスになるんで注意です。
 あと、今日の日付を表示させる関数はOracleだとSYSDATEを使用します。
 また、どのTABLEも使用しない場合はDUALというオラクル固有のディクショナリテーブルを使って表示しています。

 
そうすると差分月が479ヶ月と小数点以下アリになります。

479ヶ月って何年ヨ!計算してみます。
あ・・・もちろん1年=12ヶ月ってしってるよね。
なんで479/12をやってみます。

Windows標準電卓

Oracleさんを酷使


小数点以下は考えない(あと何日で40歳なんだ~なんていうことは気にしない!)ので
そうなると1973/10/11生まれの人は2014/10/10現在で39歳であることが判明しました。

ではきっかり整数だけ求めたい場合はどうするのか・・・

小学校3年生くらいでやった切り捨てということをします。
世の中四捨五入のほうが多いですが、切捨て・切り上げなんていう単語もあったことを思い出してください(笑)

では切り捨てってどうするのよ?!という実際の話です。

実はOracleにかかわらずSQLにはちゃんと用意されております!!
でも切り上げる関数はないの・・・捨てるか四捨五入しかないんだね・・・ショボン(´・ω・`)救済策はあるけどね

TRUNC:切り捨て
ROUND:四捨五入(まるめ)
MOD:端数の取得

数式関数でよく使うのはコレくらいでしょうか?

そのほかに高校数学でやったサインやタンジェントなんていう関数もありますが、
あまり使う機会はないですよね (苦笑)>お仕事で使ったことありますが・・・(泣)

では切り捨ての関数TRUNCをつかって同じように479÷12をOracleにやってもらいましょう。


素敵に出てきましたね。

では全部をまとめて実行してみましょう。

■実行SQL

SELECT
 TRUNC (MONTHS_BETWEEN (SYSDATE,TO_DATE('1973/10/11','YYYY/MM/DD')) /12)
FROM DUAL;

■Oracle君の答え



美しく出ましたww

ちなみに!

日付型のデータを取り扱いをする際に一番最初に気をつけないといけないことってナンだと思いますか?









わかんない?
>デナオシテコイコノヤロウ




うるう年ですよ。閏年。

Oracle君の日付計算&年齢計算の方式は日本のやり方に準じたものではないので
閏年の日の計算がことなるんで注意が必要です。
>日本だと02/29生まれの人は翌月の最初の日(=03/01)に年齢が増えるというのが法律で定められております。
  民法143条2項ただし書参照

たとえば2000/02/29生まれの人が2013/02/28に↑上でしめしたSQLで年齢を算出しようとすると

■SQL
SELECT
 TRUNC(MONTHS_BETWEEN (TO_DATE('2013/02/28','YYYY/MM/DD'),TO_DATE('2000/02/29','YYYY/MM/DD')) /12)
FROM
 DUAL;
■Oracle君の結果

となり、2013/02/28の段階ですでに13歳になってしまっているわけです。

なのでSQLを発行するプログラムで制御するもしくはSQLの中で制御する記述が必要となります。

2013年10月9日水曜日

年齢をエクセルで算出する

仕事ネタですが、調べたりきかれたりしたことを自分のログとして残しておくためのものです。

最初はエクセルねたから。

データとして
・生まれ年
・誕生日の月
・誕生日の日
というデータが別々のセルに入った状態になっている行から年齢を算出したいんですが
どうしたらよいですか?と言うことでした。
もっと省略できる方法があるかもしれませんが、わかりやすいようにしているつもりです。

まずは上記を文字列連結(文字をくっつける) させて日付型に認識させることにしました。



日付に認識させるにはExcel君ですと”/”(スラッシュ)で年/月/日にすると日付っぽく見えるので
D列=A列の値+”/” +B列の値+”/”+C列の値
という形にしました。

このままですと、標準型になっているので良くわかんないVALUE値になってしまう恐れがあるので
エクセルのセルのプロパティで日付型だよん。
ということを明示的に設定します。


E列=D列(でもプロパティで分類:「日付」、種類:「2001/3/14」にする)

これでA~Cにの誕生日情報が日付型としてE列に設定されました。

こっからが本番です。

関数で何を使えばいいのか?

・・・若干悩む(コラ)

日付差分を求める関数「DATEIF」で計算します。
↑関数名をクリックするとマイクロソフトのHPにJumpします





DATEIF(引数1(日付型),引数2(日付型),パラメータ)
で構成されています。

ここでは現在日付-誕生日から年齢を算出したいので

・引数1:誕生日
・引数2;現在日付
・パラメータ:Y(年単位)

を指定することで年齢を算出することが出来ました。


ちなみに引数2に指定しているNOW()はそのままセルに
=NOW()

と入れると


のように現在日付+スペース+時分がそのまま表示されます。

同じような関数でTODAY()というものがありますが、こちらは日付のみを表示してくれる関数です。

↑表示形式を時分までにしても0:00になる。

時間単位まで気にする場合はこれで対応可能です。

パラメータはこんな種類があります。


※本家から抜粋


自分のメモなのでこんな感じですが、お役に立てば幸いです。