SQL日付関数(年齢計算)

ITコーディネータのシュウです。
untitled

春先に京都に行った時の金閣寺の写真です。せっかく撮っていたのでアップします。

金閣寺は正式には鹿苑寺といい、写真の金閣(舎利殿)を含む鹿苑寺が世界文化遺産として登録されています。現在の金閣は、三島由紀夫の小説金閣寺にもあるように、1950年の失火で国宝であった当時の金閣が全焼した後、1955年に再建されたものです。
再建にあたっては焼失直前の姿ではなく創建時の姿を再現するとの方針が採られ、現在のような金色に光る豪華なかたちになったとのこと。
ただ、国宝や重要文化財がこのような人為的な火災や、災害などで損失してしまうことは本当に残念です。文部科学省でもこのような文化財の総合防災対策などリスク管理についてはいろいろと検討・対策を取られているようです。

実は、最近仕事も忙しくなり、少々疲れ気味。久しぶりの投稿です。
体調管理も含め、リスク管理は本当に重要ですね!

it-coordinator①-1

<本日の題材>
日付関数についての続き(年齢計算)

システムでは、生年月日をデータベースの項目に持つテーブルが存在するケースが非常に多いですね。日付の計算に関連して、今回は年齢の計算について見てみたいと思います。

データベースがOracleであれ、SQL Server であれ、年齢計算においては、以下の2つの内容を確認することになるかと思います。
1)生年月日と基準日(通常は今日)の「年」の差
2)生年月日と基準日(通常は今日)の「月日」の大小を比較し、基準日が誕生日に達してなければ -1

SQLとしてはいろいろなやり方があると思いますが、以下に例を挙げます。

Oracle:
SELECT
EXTRACT(YEAR FROM 基準日) - EXTRACT(YEAR FROM 誕生日) -CASE WHEN TO_CHAR(基準日, 'MMDD') < TO_CHAR(誕生日, 'MMDD') THEN 1 ELSE 0 END AS 年齢
FROM テーブル名 ;

SQL Server:
SELECT YEAR(基準日) - YEAR(生年月日)-
CASE WHEN RIGHT(CONVERT(VARCHAR , 基準日, 112), 4) < RIGHT(CONVERT(VARCHAR , 生年月日, 112), 4) THEN 1 ELSE 0 END AS 年齢
FROM テーブル名 ;

※YEAR(基準日) - YEAR(生年月日) は、DATEDIFF(YEAR,生年月日,GETDATE())でも同じ

例)
SELECT 社員コード
, 続柄
, CONVERT(VARCHAR,生年月日,111) AS 生年月日
, YEAR(GETDATE()) - YEAR(生年月日)-
CASE WHEN RIGHT(CONVERT(VARCHAR , getdate(), 112), 4) < RIGHT(CONVERT(VARCHAR , 生年月日, 112), 4) THEN 1 ELSE 0 END AS 年齢
FROM dbo.D社員家族
ORDER BY 社員コード, 生年月日;

年齢結果2_result

また、簡単に計算する方法として、日付型(yyyymmdd)を8桁数値に変換後に10000で割って小数点を切り捨てる方法もよく使われるようです。

Oracle:
SELECT TRUNC((TO_CHAR(基準日,'YYYYMMDD') - TO_CHAR(生年月日, 'YYYYMMDD')) /10000, 0) AS 年齢 FROM テーブル名;

※TRUNC関数は切り捨てで、第2引数が少数第何位での切り捨てかを示す。

SQL Server:
SELECT
ROUND((CONVERT(INT,CONVERT(VARCHAR(8),基準日,112))-CONVERT(INT,CONVERT(VARCHAR(8),生年月日,112))/10000,0,1) AS 年齢
FROM テーブル名;

※ROUND関数の第3引数が0以外の場合は切り捨てになります。また、FLOOR関数を使用すると、引数に対して、それ以下で最も大きい整数値を取るので同じことになります。
※閏年生まれの方も、3月1日時点できちんと年齢が上がります。

例)
SELECT 社員コード
, 続柄
, CONVERT(VARCHAR,生年月日,111) AS 生年月日
, ROUND((CONVERT(INT,CONVERT(VARCHAR,getdate(),112))-CONVERT(INT,CONVERT(VARCHAR,生年月日,112)))/10000,0,1) AS 年齢
FROM dbo.D社員家族
ORDER BY 社員コード, 生年月日;

結果は最初の処理と同じ。

注意)日本の法律(年齢計算に関する法律)上は、年齢というのは誕生日の前日で加算されるもののため、計算結果の利用目的によっては上記のような計算に1日加算するなど調整が必要になります。年齢を元に何らかの計算するような場合、年齢計算を法律に則って行うのか、一般慣習に基づいて行っていいのかよく調査してから計算式を決定する必要があります。

★また、EXCELからデータをアクセスできる環境であれば、EXCELのほうで年齢計算をできる(DATEDIF関数)ので、EXCEL側で年齢を表示させることが簡単にできます。
年齢結果Excel_result
【書式】
DATEDIF(開始日,終了日,単位)
【単位の引数】
"Y" 期間内の満年数
"M" 期間内の満月数
"D" 期間内の日数
"MD" 開始日から終了日までの日数
"YM" 開始日から終了日までの月数
"YD" 開始日から終了日までの日数

今日は以上まで

にほんブログ村 IT技術ブログへ
にほんブログ村

SQL 日付関数について(2)

ITコーディネータのシュウです。

桜2__

先週末の雨と風で桜が結構散ってしまいましたね。これはその前に撮った家の近くの庁舎にある桜の写真です。

4月に入り、子供たちもいよいよ始業式、入学式の時期になりました。わが家も子供たちが学校へ行く準備で慌ただしくしている朝の日々が戻ってきました。

朝になって、子供たちからあれがない、これがない、これを準備して!とか言われると本当に大変ですよね。前の日の夜に次の日の準備をしっかりさせるように躾けることが大事だとつくづく感じます。

it-coordinator①-1

<本日の題材> 日付関数についての続き

前回、日付型関数について少し話をしましたが、日付の計算などについて今回は見てみたいと思います。

①    何日後・何日前など、日にちを足し引きする場合:
Oracle:
 DATE型の項目に対して、足し引きしたい日数を単純にプラス 、マイナスすればよい。

SQL Server:
  DATEADD関数 (構文:DATEADD(datepartパラメータ, number, date) )でパラメータに dayを使用する。

※追記)
Oracleと同様に、足し引きしたい日数をプラスマイナスも可能です。ただし、Oracleの場合は、日数だけでなく、時間・分・秒なども 1/24 、1/24/60、1/24/60/60 などを足し引きすることで計算が可能ですが、SQL Serverでは日数までです。

例)購入日(DATE型)の7日後、7日前
Oracle:
    SELECT 購入日
      , 購入日+7  AS 購入日の7日後
      , 購入日-7  AS 購入日の7日前
      FROM テーブル名;

購入日が ’2014-03-25’ だった場合、結果は以下のようになる:
   購入日            購入日の7日後    購入日の7日前
   -----------------      -------------------     --------------------
   14-03-25         14-04-01           14-03-18

SQL Server:
    SELECT  購入日
      ,  DATEADD(day, 7, 購入日)  AS 購入日の7日後
      ,  DATEADD(day, -7, 購入日)  AS 購入日の7日前
      FROM テーブル名;

※Oracleと同様の、+7、-7 などの計算も可能です。

 
②    何か月後・何か月前など、月数を足し引きする場合:
Oracle:
ADD_MONTHS関数(構文:ADD_MONTHS (date型項目, integer) )。

SQL Server:
  DATEADD関数(構文:DATEADD(datepartパラメータ, number, date型項目) )でパラメータに month を使用する。

例)購入日(DATE型)の月末日の1ヶ月後、1ヶ月前
Oracle:
  SELECT   LAST_DAY(購入日)  AS 購入日の月末日
 ,  LAST_DAY(ADD_MONTHS(購入日,1))  AS 購入日の翌月末日
 ,  LAST_DAY(ADD_MONTHS(購入日,-1))  AS 購入日の前月末日  FROM テーブル名;

   購入日が ’2014-03-25’ だった場合、結果は以下のようになる:
     購入日の月末日     購入日の翌月末日     購入日の前月末日
       --------------------      ----------------------         -----------------
       14-03-31                  14-04-30                        14-02-28

SQL Server (2012):
    SELECT      EOMONTH(購入日)  AS 購入日の月末日
  ,  EOMONTH(DATEADD(month, 1,購入日))  AS 購入日の翌月末日
  ,  EOMONTH(DATEADD(month, -1,購入日))  AS 購入日の前月末日     FROM テーブル名;

Excel月末日_result3

※ただし、上記の月末日を取得する EOMONTH関数は、SQL Server2012から使える機能です。それ以前の場合には、翌月1日から1日引いた日付を取得するかたちが一般的ですね。いろいろな書き方があると思いますが、例えば以下のような文で今月の月末日を抽出できます。

SELECT DATEADD(DAY,-1,DATENAME(YEAR,DATEADD(MONTH,+1,GETDATE())) + '-' + DATENAME(MONTH,DATEADD(MONTH,+1,GETDATE())) + '-' + '01') as 当月末

★前回と同様、EXCELからデータをアクセスできる環境であれば、EXCELのほうで月末日を取得する関数(EOMONTH関数)があるので、EXCEL側で月末日を表示させることが簡単にできます。

Excel月末日_result2

今日は以上まで

 

にほんブログ村 IT技術ブログへ
にほんブログ村

SQL 日付関数について(1)

ITコーディネータのシュウです。

DSC00680

会社の近くで撮った写真、桜が見事に咲きました!
遠方に見えるのは、さいたま新都心のビル群

WindowsXPのサポート期限切れが迫ってきました。4月9日です。Office2003も同一日でサポートが切れますね。

先日(3/6~7)、東京駅のすぐ隣のJPタワーで行われたSecurity Days 2014でもそのことを取り上げて、セキュリティに注意を促すセッションを行うところも結構ありました。日本MSの発表では、XPとWindows8.1ではウィルス感染率に21倍もの差があるとか。。。

昨年の11月の調査時点で、サポート終了予定から約1年が経過した2015年3月時点でも、18.2%のPCがWindows XPで稼動予定という矢野経済研究所の調査報告(http://enterprisezine.jp/article/detail/5403)があり、総務省の2013/11/22の発表では自治体でも26万6千台が期限切れになるという予想報告や、最近でも個人でXPを使用している人がまだ4人に一人という調査結果を出しているところもあります。

問題は、サポートが切れることで、新しく発見された脆弱性に対してXPについてはセキュリティパッチが提供されなくなるため、その脆弱性を狙った攻撃があればそれによる被害が発生してしまう危険性が高いということです。最近は標的型攻撃とよばれるサイバー攻撃が非常に増えてきているということなので、それに対応した防御も十分考える必要が出てきていますね。

it-coordinator①-1

<本日の題材>
日付関数について

前回、日付型にどういうものがあるかという話をしましたが、日付型項目の値を表現したり計算したりする場合に、関数を使用するケースが随所に出てきます。その関数についても、OracleとSQL Serverでは違いがあるので、整理しておくと便利かと思います。

まず、よく使うのがシステム日付。

Oracle:SYSDATE
SQL Server:GETDATE()

実際にSQLでシステム日付を確認するのは、
Oracleでは、
SELECT SYSDATE FROM dual;
SQL Serverでは、
SELECT GETDATE();

そして、日付型項目を日本語の日付表現に直して表すとき、西暦の4桁の年月日までか、年月までか、年だけの表記にするか、それとも時刻まですべて表現するのかなど、いろいろとシステムによって項目ごとに使い分ける場合があると思います。

今回は、この日付のフォーマットに関して少し上げてみたいと思います。

Oracleの場合は、TO_CHAR関数を使用して、フォーマットを設定しますが、SQL Serverの場合は、CONVERT関数を利用することが多いと思います。

例)
①yyyy/mm/dd という表示にしたい
Oracle:
SELECT TO_CHAR(日付項目, ‘YYYY/MM/DD’) FROM テーブル名;
SQL Server:
SELECT CONVERT(VARCHAR, 日付項目, 111) FROM テーブル名;

②yyyy-mm-dd hh:mi:ss というように日付+時刻(24時間表記)で表示したい
Oracle:
SELECT TO_CHAR(日付項目, ‘YYYY-MM-DD HH24:MI:SS’) FROM テーブル名;

SQL Server:
SELECT CONVERT(VARCHAR, 日付項目, 120) FROM テーブル名;

結果はこんな感じ:
2014-03-31 14:46:39

③和暦で表示したい
Oracle:
SELECT TO_CHAR(日付項目, 'EEYY"年"mm"月"dd"日"', 'nls_calendar = ''Japanese Imperial''') 日付 FROM テーブル名;

結果はこんな感じ:
日付
----------------------------
平成26年3月31日

※Oracleの書式について
E : 元号の略語(大正:T、昭和:S、平成:H)
EE: 元号(大正、昭和、平成)

和暦変換する場合は'nls_calendar = ''Japanese Imperial'''で「nls_calendarオプション」のカレンダを指定するかたちになります。

SQL Server:
SQL Serverでは、実は和暦に変換する関数は持っていないため、SQLを駆使してこれを実現するケースが多いと思います。例えば元号を表すためには

SELECT
Case when 日付項目 > '19890107' then '平成'
when日付項目 > '19261224' then '昭和'
when日付項目 > '19120729' then '大正'
when日付項目 > '18680124' then '明治'
else 'その他' end 年号
というようなかたちでSQLで設定が必要です。

ただし、例えば結果をEXCELで表示するというように、EXCELからデータをアクセスできる環境であれば、EXCELのほうで日付データに対して和暦の表示を行うことができるので、SQL Serverのデータでも、簡単に和暦に変換することが可能になります。

和暦全体

EXCELはいろいろと関数を持っているので、使えば結構便利ですよね。

なお、SQL ServerのCONVERT関数についての仕様やパラメータについては、以下のサイトで確認できます。
http://msdn.microsoft.com/ja-jp/library/ms187928.aspx

今日は以上まで

にほんブログ村 IT技術ブログへ
にほんブログ村