web-dev-qa-db-ja.com

MySQLの日、月、年のフィールドから日付を作成する

現在、ドキュメントを表示し、メンバーがこれらのドキュメントをいくつかの異なるパラメーターで検索できるようにするアプリケーションを開発しています。そのうちの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;
37
TGuimond

STR_TO_DATE() 関数を使用できます。

35
Sachin Shanbhag

年、月、日の整数値がある場合、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';
45
Joe Holt

それからソート可能な日付文字列を作成するには、ビットを結合する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遅くなることに注意してください。また、年、月、日のフィールドにインデックスがあることを確実に確認する必要があります。

17
Spudley

これを行う最も簡単な方法は次のとおりです。

DATE(CONCAT_WS('-', year, month, day))

@pbarneyが以前指摘したように、LPADは必要ありません。別の日付オブジェクトと比較する場合、MySQLが自動的にキャストするため、DATEでラップすることは厳密には必要ありません。

some_date_field > CONCAT_WS('-', year, month, day)

4
Gannet

CONCAT()を使用して、1つのフィールドにして比較します。

連結後の日付と比較できるかどうかわかりません。

整数として比較できます。

年月日を連結し、この20101017のような整数を作成して比較します。

うまくいけば:)

1
zod