現在、ドキュメントを表示し、メンバーがこれらのドキュメントをいくつかの異なるパラメーターで検索できるようにするアプリケーションを開発しています。そのうちの1つは日付範囲です。
私が抱えている問題は、データベーススキーマが自分で開発されたものではなく、データベースの作成者が「日」、「月」、「年」のフィールドを持つ「日付」テーブルを作成したことです。
テーブルから特定の日、月、年を選択し、SQLで日付オブジェクトを作成して、BETWEENを使用してユーザーが入力した日付を比較できるようにする方法を知りたいです。
日付テーブルの構造は次のとおりです。
CREATE TABLE IF NOT EXISTS `date` (
`deposition_id` varchar(11) NOT NULL default '',
`day` int(2) default NULL,
`month` int(2) default NULL,
`year` int(4) default NULL,
PRIMARY KEY (`deposition_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
STR_TO_DATE() 関数を使用できます。
年、月、日の整数値がある場合、MAKEDATE()とDATE_ADD()を組み合わせてDATETIMEを作成できます。一定の日が1のMAKEDATE()は、指定された年の最初の日のDATETIMEを提供し、DATE_ADD()で月と日を追加できます。
mysql> SELECT MAKEDATE(2013, 1);
+-------------------+
| MAKEDATE(2013, 1) |
+-------------------+
| 2013-01-01 |
+-------------------+
mysql> SELECT DATE_ADD(MAKEDATE(2013, 1), INTERVAL (3)-1 MONTH);
+---------------------------------------------------+
| DATE_ADD(MAKEDATE(2013, 1), INTERVAL (3)-1 MONTH) |
+---------------------------------------------------+
| 2013-03-01 |
+---------------------------------------------------+
mysql> SELECT DATE_ADD(DATE_ADD(MAKEDATE(2013, 1), INTERVAL (3)-1 MONTH), INTERVAL (11)-1 DAY);
| DATE_ADD(DATE_ADD(MAKEDATE(2013, 1), INTERVAL (3)-1 MONTH), INTERVAL (11)-1 DAY) |
+----------------------------------------------------------------------------------+
| 2013-03-11 |
+----------------------------------------------------------------------------------+
OPの質問に答えるために:
SELECT * FROM `date`
WHERE DATE_ADD(DATE_ADD(MAKEDATE(year, 1), INTERVAL (month)-1 MONTH), INTERVAL (day)-1 DAY)
BETWEEN '2013-01-01' AND '2014-01-01';
それからソート可能な日付文字列を作成するには、ビットを結合するCONCAT
と、月と日のフィールドが2桁の長さであることを確認するLPAD
が必要です。このようなもの:
_CONCAT(`year`,'-',LPAD(`month`,2,'00'),'-',LPAD(`day`,2,'00'))
_
それができたら、BETWEEN
を使用できるようになります。これは、ソート可能な形式になっているためです。ただし、それらを実際の日時フィールドに変換する必要がある場合は、UNIX_TIMESTAMP()
で全体をラップしてタイムスタンプ値を取得できます。
したがって、次のような結果になります。
_SELECT UNIX_TIMESTAMP(CONCAT(`year`,'-',LPAD(`month`,2,'00'),'-',LPAD(`day`,2,'00'))) as u_date
WHERE u_date BETWEEN timestamp_1 and timestamp_2
_
ただし、これは、フィールドがそもそも単純なタイムスタンプであった場合よりもmassively遅くなることに注意してください。また、年、月、日のフィールドにインデックスがあることを確実に確認する必要があります。
これを行う最も簡単な方法は次のとおりです。
DATE(CONCAT_WS('-', year, month, day))
@pbarneyが以前指摘したように、LPADは必要ありません。別の日付オブジェクトと比較する場合、MySQLが自動的にキャストするため、DATEでラップすることは厳密には必要ありません。
some_date_field > CONCAT_WS('-', year, month, day)
CONCAT()を使用して、1つのフィールドにして比較します。
連結後の日付と比較できるかどうかわかりません。
整数として比較できます。
年月日を連結し、この20101017のような整数を作成して比較します。
うまくいけば:)