こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

1ヶ月に土日は何日あるか

1ヶ月に土日は何日あるかをSQLで調べたいと思ってます。
指定した年月に土曜日が何回あるかがわかるような便利な関数はないでしょうか?
教えてください。

投稿日時 - 2008-08-09 17:28:40

QNo.4239554

困ってます

このQ&Aは役に立ちましたか?

23人が「このQ&Aが役に立った」と投票しています

回答(9)

すいません、#8です。オリンピックを見ながらずっとカレンダーを眺めていたのですが、もっと簡略化できますね。

年間カレンダーとしては、#8にもあるとおり全部で14パターンですが、各月ごとのカレンダーのパターンは、つまるところ28パターンに全て集約できますね。

ある月の一日が日曜日で始まる場合、月曜日で始まる場合、・・・で、7パターン。それに加えて、閏年がある時も踏まえた上で、各月ごとのカレンダーの末日は28日、29日、30日、31日の4パターンのみです。よって、7×4より全部で28パターンですね。

で、土曜日の日数のみを表すテーブルを、以下のように作成します。(年間カレンダーより、規則的にこの様な結果になると思います。)

\|28 29 30 31
ーーーーーーーーーー
日|4 4 4 4
月|4 4 4 4
火|4 4 4 4
水|4 4 4 4
木|4 4 4 5
金|4 4 5 5
土|4 5 5 5

上記のテーブルを元に、以下のような条件でSQL文を記述すれば、すぐに指定した年月に土曜日が何回あるかがわかることと思います。

列(属性)→LAST_DAY関数を用いて、各月の末日が4つのうちの何れかを求める。
行(組)→TO_CHAR関数を用いて、各月の一日が何曜日から始まるのかを求める。

ちなみに、日曜日の日数のみを表すテーブルは敢えて作成しないでおきますが、上記と同様にすればすぐに専用のテーブルを作成できることと思います。

投稿日時 - 2008-08-14 23:51:45

OracleのSQLでは、ダイレクトにそのような処理をする関数が用意されていないため、一般的にはASPなどのプログラミング側で処理をすることになるかと思います。Javaなどであれば、恐らくコレクションなんかを用いるんじゃないかなあ、と。(PL/SQLに関しては、専門外なので割愛。)

ただ、あくまでもSQLにこだわるのであれば、以下のようなアルゴリズムもあります。

そもそも、カレンダーというのは全部で14パターンあり、毎年そのどれかのパターンを繰り返し使用しているということになっています。

具体的には、元旦が月曜日の時、火曜日の時、・・・で、7パターン。それに、閏年の場合がそれぞれにありますから、×2で14ですね。(詳細については、「万年カレンダー」でググってみてください。)

今回の場合、インプットは「年」、「月」、「曜日」で、アウトプットが「日数」ですから、以下のようなテーブル2つ[SAT_DUAL],[SUN_DUAL]を事前に用意しておきます。

テーブル[SAT_DUAL] or [SUN_DUAL]
列(column)→1月、2月、3月、4月、5月、6月、7月、8月、9月、10月、11月、12月の12つ。
行(row)→「元旦_月」、・・・、「元旦_日」、「閏年_元旦_月」、・・・、「閏年_元旦_日」の14つ。

列の指定については、インプットの「月」をそのまま利用すればいいと思います。

行の指定については、インプットの「年」が4で割り切れるかで閏年かどうかを判断し、且つその「年」の元旦が何曜日なのかをOracleのTO_CHAR関数で求め、その結果をWHERE句に記述すればいいと思います。

もちろん、土・日両方の場合は、上記2テーブルの結果を足し算すればいいわけですね。

ちなみに、各テーブルのデータ(具体的な日数)については、以下のサイトなどを元に一つずつ入力しておいてください。(最初だけは、これが大変です。)

「万年カレンダー」
http://koyomi.vis.ne.jp/sub/cal_year.htm


以上、実際に試してはいませんがアドバイスということで。

投稿日時 - 2008-08-14 17:38:53

ANo.7

いろいろな意見があって非常に興味深いですが、確かに1回きりの作業ならSQLではやらないでしょうね。ただ、DBプログラミング(PL/SQL)だったら、そういうニーズがあればDBサイドに欲しいと思うかもしれないなとは思います。
考え方は難しくなくて、TO_CHAR(日付,'d')で日曜を1とする番号が取得できますから、土曜、日曜がそれぞれ7番目に来るように日数を補った上で、7で割り、商を合計するだけです。
長いので関数にした方がいいでしょうが。。

指定した日の属する月の土日の数
CREATE OR REPLACE FUNCTION f_NUMHOL(P_DATE DATE)
RETURN NUMBER
AS
BEGIN
RETURN (
TRUNC(
(TO_CHAR(LAST_DAY(P_DATE),'dd')
+TO_CHAR(P_DATE-TO_CHAR(P_DATE,'dd')+1,'d')-1)/7,0)
+TRUNC(
(TO_CHAR(LAST_DAY(P_DATE),'dd')
+MOD(TO_CHAR(P_DATE-TO_CHAR(P_DATE,'dd')+1,'d')+5,7))/7,0)
);
END;

投稿日時 - 2008-08-14 15:26:16

ANo.6

1ヶ月に土日が何日あるかというのはデータベースの
内容によらずに一定なので、データベース処理を行う
のが目的のSQLで処理をするのは一般的ではありません。
どうしても必要なのであれば、私なら年月と土日の数
から成るテーブルを作りますが?

投稿日時 - 2008-08-14 13:34:36

ANo.5

がるです。
えと…私が「奇異である」と感じたのは。

SQLは、本質的に「リレーショナルデータベースにおいて、データの操作や定義を行うための問い合わせ言語」なので。
基本的には「データの取得や格納をSQLで行い」「それらのデータをプログラム側で処理する」というのが、自然な流れになります。
無論、SQLでも「可能」ではあるのですが。
「可能」と「適切」の間には、深い隔たりがあるので。

もし、Cosmo2007さんが「趣味や個人的なもので」作成されているのであれば、それは個人の範疇だからよろしいと思うのですが。
もし業務でなさっているのであれば、現場の流儀等、特別な理由がないかぎり、そういった事はSQL(DB)側よりもプログラム(ビジネスロジック)側でやるほうがよろしいかと思われます。

以上、老婆心ではありますが。

投稿日時 - 2008-08-11 10:51:06

遊び半分でいろいろとググっていたら、以下のサイトを発見。

OracleSQLパズル
5-18 期間内の特定の曜日の数を取得
http://oraclesqlpuzzle.hp.infoseek.co.jp/5-18.html

ただし、私みたいに中学受験を経験していない者にとっては、「植木算」からの勉強が必要のようですね。

参考URL:http://jibun.atmarkit.co.jp/lskill01/rensai/bronzesql03/bronzesql01.html

投稿日時 - 2008-08-09 22:52:04

ANo.3

そのような組み込み関数はないと思います。自分で作るよりないですよね。その場合、インプットしなければならない引き数は、月と1日の曜日の二つになります。7×4=28ですから、2月でも4回あり、7×5=35ですから、6回はないことになります。そこで5回あるかないかはその月が何曜で始まったかによることになります。2月は通常では4回、閏2月の場合は土曜で始まったときのみ5回、小の月では金曜 土曜で始まったときは5回、大の月では木曜、金曜、土曜で始まったときが5回となります。曜日を数字で表すことにすると割合簡単にルーチンが組めますよ。日曜はこれが一つずつ前進しますよね。

投稿日時 - 2008-08-09 18:11:34

お礼

ご回答ありがとうございます。

>そのような組み込み関数はないと思います。

そうなんですか。

>自分で作るよりないですよね。

わかりました。
ゴリゴリ頑張ってみます。

投稿日時 - 2008-08-09 18:56:27

ANo.2

その検索を行おうとしているデータベース上には、どのような項目が定義されているのでしょうか?

投稿日時 - 2008-08-09 17:50:11

お礼

ご回答ありがとうございます。

>その検索を行おうとしているデータベース上には、どのような項目が定義されているのでしょうか?

DBの項目は色々あるのですが、FROM dual で上手くできないかと思いまして…。

投稿日時 - 2008-08-09 18:54:45

ANo.1

がると申します。
えと…本質的には、そもそういう事をSQLでやる事自体が少々奇異であるように思われるのですが。
普通にプログラム上でやらない、あるいは出来ない理由などがあるのでしょうか?

投稿日時 - 2008-08-09 17:36:58

お礼

ご回答ありがとうございます。

>えと…本質的には、そもそういう事をSQLでやる事自体が少々奇異であるように思われるのですが。

そうなのですか?

>普通にプログラム上でやらない、あるいは出来ない理由などがあるのでしょうか?

出来ない理由はないです。
ただSQLでできるのなら、そのほうが便利かと思ったのです。

投稿日時 - 2008-08-09 18:52:33

あなたにオススメの質問