*

[SQL, DB2]FETCH FIRSTで指定した行数データを取得する(営業日計算)

公開日: : 最終更新日:2015/01/11 AS400, i Series, SQL, System i

営業日計算

営業日を計算するのは結構面倒です。
特に独自のテーブルだと非常に厄介です。

例えば以下を考えます。
テーブル名:carrendar

days(integer) status(character)
20140201 営業日
20140202 営業日
20140203 休日
20140204 営業日
20140205 営業日

※話を単純にするために、日付を数値で保持しています。
このデータで、2014/02/02の2営業日後はどのように計算すればよいでしょうか。

適当に考えると、以下のフローで実現は可能です。

  1. 翌日(2014/02/03)のデータを取得。
  2. 翌日は営業日かどうかを調べる。
  3. 営業日であればカウントアップ
  4. カウントが2でなければ最初に戻り更に翌日を調べる
  5. カウントが2になったら、その日付を取得し、2営業後の日付とする。

単純です。
しかし、これではselect文の発行が繰り返されることになります。
1日2日の計算では問題ありませんが、例えば100日の計算ともなると、かなりの処理時間が掛かります。

ではどのようにすればいいでしょうか。

営業日だけを抽出して2日後を取得

上記テーブルであれば以下のSQLです。

select * from carrendar
  where status = '営業日'
    and days > 20140202
  order by days ASC;

このSQLで結果を取得し、レコードを2回(2日分)読み込めば目的の日付が取得できます。
逆に20140204の2営業日前であれば

select * from carrendar
  where status = '営業日'
    and days < 20140204
  order by days DESC;

このようになるかと思います。

しかしながら、これでもスマートでない。
100営業日前を計算するのであれば、大きなテーブルを取得する必要がありますし、またレコード読み込みの回数も100回になってしまいます。
であれば、取得するレコードを逆順にして、最初のレコードを読めばいい、ということで

select * from carrendar
  where status = '営業日'
    and days > 20140202
  order by days DESC;

とすると、カレンダーマスタの最大日付から取得することになり、意図した結果が得ることが出来ません。

結論

上記を踏まえると、レコードを特定して、そのレコードからX行までを取得し、逆順に並べ替えれば欲しいデータを得ることが出来そうです。

欲しい行数を取得

DB2ではFETCH FIRSTを利用します。
具体的には以下の様になるでしょう。

select tmp.days from(
  select * from carrendar
    where status = '営業日'
      and days > 20140202
    fetch first 2 rows only
) as tmp
  order by days DESC;

解説

(1)20140202よりも大きい営業日のレコードを取得して、tmpという名称のテーブルにし、(2)逆順に並び替えています。

(1)のSQL部分と実行結果イメージ

select * from carrendar
  where status = '営業日'
    and days > 20140202
  fetch first 2 rows only
days(integer) status(character)
20140204 営業日
20140205 営業日

(2)のSQL部分と実行結果イメージ

select tmp.days from(
  (1)のSQL
) as tmp
  order by days DESC;
days(integer) status(character)
20140205 営業日
20140204 営業日

(2)の最初のレコードが欲しいデータですね。

 

なお、以下が2行だけ取得する構文です。

fetch first 2 rows only

この構文で2行分のテーブルを取得し、そのデータを逆順に読み出すことにより、最初のレコードが取得したい2営業日後のレコードになります。

営業日前

20140204の2営業日前では以下のようになります。

select tmp.days from(
  select * from carrendar
    where status = '営業日'
      and days < 20140202
    order by days DESC
    fetch first 2 rows only
) as tmp
  order by days ASC;

解説

遡ることになるので、最初のselect(2行目)ではdaysを逆順に並び替えて読み出す必要があります。

ad

関連記事

logo

[java, jt400]AS400ネイティブ環境でjavaを起動し、ファイルに対するSQLを実行する方法。

日本語資料なさすぎだから自分で作ります。 AS400がでjavaを起動して、自分のファイルを見に行

記事を読む

logo

[SQL]読みづらいSQLとさらば! SQLのインデントと改行のタイミング

SQLってインデントやら改行の仕方がプログラムと違うんです。 ここら辺を適当に書かれると非常にSQ

記事を読む

wannabenote

[Oracle, SQLDeveloper]Oracleの構築とSQLDeveloperを設定、GUIでテーブルを表示するまで

Oracleを使い込む必要が出来たので、その備忘録です。 とりあえずはインストールから環境構築して

記事を読む

logo

[jt400, Java]AS400のファイルを更新するためにREADした時にRecord Lockをかける

RPG3なんかだと更新用のファイルはREADの瞬間に自動でレコードロックがかかります。 で、それを

記事を読む

logo

[C#]AS400に対してODBC接続でトランザクションによりSQLを実行する。

データベースに対するトランザクション処理 と銘打ちましたが、要するに安全にinsert文などを実行

記事を読む

logo

[jt400, Java]レコードレベルアクセスの実現

到着順 AS400のファイルシステムですと、レコードを読み込んで、処理して、出力して、次のレコード

記事を読む

logo

AS400のインターフェースファイル

AS400にODBC接続するときに、ライブラリ名一覧が欲しい場合があります。 さて、それでは、

記事を読む

cwbx.dll 参照の追加

[C#,AS400]C#でAS400のプログラムCallとコマンドの実行方法。

PCのプログラムからCall AS400のRPGPGMをPCから呼び出ししたいときがあります。

記事を読む

logo

PCからAS400のコマンドを実行する方法

C#でAS400のRPGを呼んだりコマンドを実行する方法はこちら→C#でAS400のプログラムCal

記事を読む

logo

[C#]AS400のメンバーを指定してデータにアクセスする

◆前提条件◆ CliantAccessをインストールしている。 .NET Framework3.

記事を読む

ad

Message

メールアドレスが公開されることはありません。

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

ad

  •  Auther;わなび

     「オープン系得意だよね? 俺のPCの調子悪いんだけど」という無茶振りから解き放たれゲームエンジニアに。
    C#とかUnityを扱います。
    Twitterフォロー大歓迎です。
    githubアカウント→wannabenote
  • follow us in feedly
PAGE TOP ↑