• ベストアンサー

イベント日付(複数または連続した日付)をデータベースで管理する方法について

イベント情報のデータベースを作成していますが、 どのように日付情報をデータベースとして持たせたらよいのか悩んでいます。 効率的な方法がありましたら教えていただけると幸いです。 長文になり、失礼いたします。 [目的] イベント毎に開催日時や主催者などのデータベースを構築し、開催日時で検索を行いたい。 [悩みどころ] 開催日時が、”2008年9月24日”のように1日で終わるものであれば問題ないのですが、”2008年9月24~28日”のような連続した日付や、”2008年9月24日、2008年9月26日”のような連続しない複数日の場合に、どのようなデータベース構造を持たせるべきなのか悩んでいます。 [現状の案] 現状は、イベントテーブルと日付テーブルを分けて管理する方法を考えていますが、これが一般的な方法なのでしょうか。 <EVENT_TABLE> event_id:(auto increment) event_name:イベントの名前 <DATE_TABLE> date_id:(auto increment) event_id:EVENT_TABLE.event_id を指すID date:イベント開催日単日 イベントの開催日が1日であれば、一つのevent_idと一つのdate_id。 イベントの開催日が、連続した三日であれば、一つのevent_idと三つのdate_id。 イベントの開催日が、連続しない三日であれば、一つのevent_idと三つのdate_id。

質問者が選んだベストアンサー

  • ベストアンサー
  • dell_OK
  • ベストアンサー率13% (742/5653)
回答No.3

一般的かどうかはわかりませんが、 複数のテーブルをJOINするのが好みかどうかとか、 データベースの効率を考えるとどうかと言うので決まってくるのでしょう。 私はあまりJOINしたくないと言う気持ちだけの話でANo.1のご回答にあるような感じでしてしまいます。 これに、連続しない開催の場合は、初日のイベントIDを他の開催日のデータに持たせて関連づけておけば、重なるデータ(イベント名など、他詳細情報もこちらに記録されるのだと思っています)は初日の方にだけ記録しておいても、なんとかなるのかなと思います。 と言うのが、私の今までの経験から思いつく事でした。 ANo.2で質問者様の方法で十分との事でしたので、よくよく考えてみると、なるほどその方が拡張性があるのかなと思ったりもしています。 データベース効率はどちらがいいのかわかりませんが、今お考えになられている方法から遠のくと難しくなるかも知れませんので、別の問題が起こらない間はそのまま進めてみられた方がいいのかと思います。 「DATE_TABLE」は、連続していようとしていまいと関係なく、開催している日分のデータがあると言う事と考えてよろしいでしょうか。 日時で検索するのでしたら、「DATE_TABLE」には、その日の開始時刻と終了時刻を記録しておくようになるのかも知れません。 最終日だけ早めに終わったりするようなイベントもあるのでしたら、「EVENT_TABLE」側で時刻を持つよりもいいのかなと思います。

mmei
質問者

お礼

ご回答ありがとうございます。 投入データを分析すると、明らかに1日のイベント、または連続した日のイベントが多くを占めているようで、連続しないイベントはあまりないことに気づきました。 そのため、連続しない日付のイベントについては、イベント投入フォームにコピーなどの機能を用意して、複数のEvent_idとして管理する方向で検討中です。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (4)

  • dell_OK
  • ベストアンサー率13% (742/5653)
回答No.5

ANo.3です。 chukenkenkou様、ありがとうございます。 なるほど、よくわかりました。 私が誤解していました。 質問者様へ、惑わせていたら、すみませんでした。

mmei
質問者

お礼

複数の実現方法を得ることが出来まして、今後のDB設計時など、 大変重宝したと感じています。 ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。
回答No.4

#1です。 #1の回答は、「表を分けてジョインしないで」と誤解された人もいるようですが、そうではなく、提示された表の分け方で、「イベント開催日単日」としているところを、「開始日と終了日とすればいいのでは?」という意味です。連続する開催の場合は、全日付の行を持たなくても、開始日と終了日の行があればいいということですので、念のため。

mmei
質問者

お礼

十分に理解ができました。 補足ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。
  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.2

連続しないものもあるなら、現状の案で提示なさっている方法で 十分です。 >イベントの開催日が、連続しない三日であれば、一つのevent_idと三つのdate_id。 これは「一つのevent_idと二つのdate_id」ですね?

mmei
質問者

お礼

ご説明が不足しておりすみませんでした。 「連続しない三日であれば、一つのevent_idと三つのdate_id」についてですが、たとえば、イベントAの開催日が、1月1日、2月2日、3月3日のように連続しない三日だった場合には、ひとつのevent_id=イベントAと、上記の三つの開催日を持つdate_idになるのかなと考えた次第です。

全文を見る
すると、全ての回答が全文表示されます。
回答No.1

連続した日にちは、開始日と終了日を持てばいいと思います。 一日のみの開催は、開始日と終了日で同じ日付を入れておく。 連続しない開催の場合は、開催数分の行で管理する。 上記のようにするのが、操作性などを考えると良いと思います。

mmei
質問者

お礼

早々のご回答ありがとうございました。 まずは、ご提案いただきました方法でDBを構築し、 サンプルデータを複数投入して不都合でないか否かをみているところです。 今のところは、問題ないように思います。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 日付毎の集計方法

    下記のようなテーブル構成で、過去一週間の毎日について、登録した人の数を知りたいです。 ■テーブル名 my_table システムに登録すると,IDが付与され,登録した日付が記録されます。 ---------------------------------------- id(intger) | reg_date(登録した日付,timestamp) ---------------------------------------- 以下のようなSQLを考えたのですが、timestampが「2005-12-01 00:00:00+09」という細かい日付になっているので、これでは「1日」毎の集計にはなりません。 この場合、どう表現すればよいでしょうか? SELECT sum(reg_date) from my_table where ('now' - reg_date < '7days') GROUP BY reg_date order by reg_date

  • SQL文を教えてください。

    特定の日付Xを指定した場合、 以下のような結果になるSQL文を教えてください。 よろしくお願いします。 1) 日付X = 2003-12-17 の場合 ID table_A_DATE table_B_DATE table_C_DATE ------------------------------------------------ 001 2003-12-10 2003-12-12 2003-12-14 002 2003-12-15 ---------- 2003-12-16 003 2003-12-06 2003-12-10 ---------- 004 2003-12-08 ---------- ---------- 2) 日付X = 2003-12-11 の場合 ID table_A_DATE table_B_DATE table_C_DATE ------------------------------------------------ 003 2003-12-06 2003-12-10 ---------- 004 2003-12-08 ---------- ---------- table A(テーブルAには全ユーザのデータがあります) ID DATE ------------------ 001 2003-12-10 002 2003-12-15 003 2003-12-06 004 2003-12-08 table B ID DATE ------------------ 001 2003-12-12 003 2003-12-10 table C ID DATE ------------------ 001 2003-12-14 002 2003-12-16

  • データベースに格納されている期間から任意の日付で抽出

    PHP + Mysqlにてイベント管理のプログラムを作成しています。 データベースのイベントtableに、 イベントの開始年月日と終了年月日のフィールドがあります。 (開始年月日2008-10-01、終了年月日2008-12-01) そこで、select文にて、任意の年月日に開催しているイベントを抽出したいと思います。 (検索年月日2008-10-15) 逆のことなら、(検索が開催期間で、テーブルには開催年月日のみ) between ○○○and○○○でできると思いますが、 上記のことはどのような考え方で行えばよろしいでしょうか? このテーブルのままでは無理なのでしょうか? こちらのカテゴリかmysqlのカテゴリか迷ったのですが、 お分かりになりましたら、ご回答よろしくお願い致します。

    • ベストアンサー
    • PHP
  • 時間の重複を加味した連続時間SQL文

    EVENT --+-------------------------+----------------+ id| EVT| start_date | end_date --+-------------------------+-----------------+ 0 |AAAA| 2013-06-01 10:00 | 2013-06-01 14:00| --+-------------------------+-----------------+ 1 |BBBB| 2013-06-01 12:00 | 2013-04-01 18:00| --+-------------------------+-----------------+ 2 |CCCC| 2013-06-02 10:00 | 2013-06-05 12:00| --+-------------------------+-----------------+ 3 |DDDD| 2013-06-02 13:00 | 2013-06-05 18:00| --+-------------------------+-----------------+ 4 |EEEE| 2013-06-02 14:30 | 2013-06-05 17:00| ↑こんな感じでイベントを管理するテーブルがあります。 イベントの開催時間の重複を加味して何らかのイベントのある 連続した時間帯のみ取り出すSQLを書きたいのですが、 いい案はありますでしょうか? 結果的には以下の様な情報が取り出したいです。 2013-06-01 10:00 - 18:00 2013-06-02 10:00 - 12:00 2013-06-02 13:00 - 18:00 ID 0と1は連続してるので 10:00 - 18:00 ID 2はどれとも連続してないので 10:00 - 12:00 ID 4はID3の中にあるので無視

  • データベースと正規化とINSERT文について

    ただいま以下の一つのテーブルを正規化しようとしています。 テーブル:英単語 フィールド:単語、意味1、意味2、意味3、品詞、分類1、分類2、分類3、例文、難易度、ID(主キー・オートインクリメント) これを以下のように分けました。(分類とは単語の分類です。例えば year なら意味は 年 で分類は 時間 とか 単位 とか属性を入れたいのです。) ****** テーブル:英単語 フィールド:単語、意味1、意味2、意味3、分類ID、分類ID、分類ID、例文ID、難易度、ID(主キー・オートインクリメント) テーブル:分類 フィールド:分類名、ID(オートインクリメント 主キー) テーブル:品詞 フィールド:品詞名、ID(オートインクリメント 主キー) テーブル:例文 フィールド:例文、ID(オートインクリメント 主キー) ****** (1)これで正規化できているでしょうか? もしできていないなら、どうすればよいでしょうか? (2)また、仮にこのままデータベースを作るとすると、INSERTの時に英単語テーブルの分類IDに、分類テーブルのIDをひもづけるにはどうしたら良いのでしょうか? INSERT INTO 分類 (分類名) VALUES("時間") のあと、オートインクリメントされたIDを取り出して、英単語テーブルに入れるにはどうしたらいいでしょうか。

    • ベストアンサー
    • MySQL
  • mysql のテーブルの名前は数字ではだめですか

    phpmyadmin で数字名前のテーブル上手く作りましたが。。なぜかmysqlで $query = "CREATE TABLE 2234( id int AUTO_INCREMENT key, 入力日 VARCHAR(10 ) $squery1 = mysql_query($query); (create table "2234"( ...)もcreat table '2234'(..)もだめ) なぜかエラーが出ました?

  • 複数のテーブルに対しSQLでデータを取得する方法

    下記の2つのテーブル、及びソースコードがあります。 【sample_db】 CREATE TABLE IF NOT EXISTS `sample_db` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL, `path` varchar(255) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `path` (`path`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=11 ; INSERT INTO `sample_db` (`id`, `name`, `path`) VALUES (1, '2010年', '.1.'), (2, '6月', '.1.2.'), (3, '28日', '.1.2.3.'); 【sample_students】 CREATE TABLE IF NOT EXISTS `sample_students` ( `id` int(11) NOT NULL AUTO_INCREMENT, `sample_db_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=11 ; INSERT INTO `sample_students` (`id`, `sample_db_id`) VALUES (1, 1), (2, 2), (3, 3); 【ソースコード】 <body> <?php $link = mysql_connect('localhost', 'データベースユーザ名', 'データベースパスワード名'); mysql_select_db('データベース名', $link); $sql = <<<SSS SELECT `SampleDb`.`id` , `SampleDb`.`name` , `SampleDb`.`path` , `sample_students`.`id_count` FROM `sample_db` AS `SampleDb` LEFT JOIN ( SELECT count( `sample_db_id` ) AS `id_count` , `sample_db_id` AS `sample_db_id` FROM `sample_students` GROUP BY `sample_db_id` ) AS `sample_students` ON ( `SampleDb`.`id` = `sample_students`.`sample_db_id` ) ORDER BY `SampleDb`.`path` SSS; $query = mysql_query($sql, $link); $p = 0; while ($row = mysql_fetch_array($query)) { $starter= "\n"; $rp = intval( $row['depth'] ); if( $p< $rp ){ // 子の開始 $p ++; $starter .= "<ul><li>"; }else { if( ($dp= $p-$rp) >0 ){ $p = $rp; $starter .= str_repeat('</li></ul>', $dp); } $starter .= '</li><li>'; } echo "$starter $row[1]: $row[2] :【$row[3]】"; } echo "\n". str_repeat('</li></ul>', $p) ; mysql_close($link); ?> </body> 上記の表示結果は、下記のようになります。 【表示結果】 2010年: .1. :【1】 6月: .1.2. :【1】 28日9: .1.2.3. :【1】 これを下記のような表示結果に変更する事は可能でしょうか? 2010年: .1. :【3】 6月: .1.2. :【2】 28日: .1.2.3. :【1】 やりたい事は、2010年には、それ以下に所属する合計を出したいと思いました(6月なども同様です)。 現在は、2010年そのものしか出せておりません。 pathフィールドの検索の仕方を考慮する必要があると思いましたが、どのようなSQL文を書けば良いか分からなかった為、 アドバイスいただける方がいらっしゃいましたら、ご教示の程よろしくお願いします。

    • ベストアンサー
    • PHP
  • SQLで連続したカラムが何個あるかを求める方法

    お世話になっております。 PHPとmysqlでサイトを作っておりまして、そのログを分析しようとしています。 あるテーブルにユーザー名とログイン日付が入ったテーブルが有ったとして、その中で連続○日ログインしていた人は○人という結果を取りたいと考えているのですがこれをSQLで処理する方法はありますでしょうか? 今のところ、PHPで全データを取った後にPHP側で処理するしかないかと思っているのですが、件数が多いため可能であればmysql側で処理したいと思っています。 日付はUNIXTIMEに直すなどすればINTEGERに変換出来るとは思っているのですが、日付型(難しいようであればINT型の連続値でも問題ありません)でSQLで処理出来る方法はあるのでしょうか? ○○結合をすれば良いなど手がかりなど教えていただけると助かります。 ■テーブル username   login_date ほげ      2014/5/1 ほげ      2014/5/2 ほげ      2014/5/3 ほげ      2014/5/4 ふーばー   2014/5/2 ふーばー   2014/5/3 あああ     2014/5/1 あああ     2014/5/3 あああ     2014/5/4 ■ほしい結果 4日連続   1名 2日連続   2名

  • 複数テーブルの削除

    お世話になります。 うまい資料が見つからなかったので質問させてください。 例えば、下記のようなテーブルが3つあったとします。 <table1> id name date <table2> id tel <table3> id etc name,date,tel,etcは同タイミングで一括に登録され、3テーブルともに共通のidで保存されます。 この時、table1のdate(日付が入ります)が30日以上経過しているデータについて、いずれのテーブルからも削除したいと思っています。 こんな場合、どんなSQL文を書けば良いのでしょうか? お分かりになる方、何卒よろしくお願いしますm(_ _)m

    • ベストアンサー
    • MySQL
  • PHPとMysqlを使用した集計表の作り方

    --------------媒体-------------- CREATE TABLE IF NOT EXISTS `media` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; INSERT INTO `media` (`id`, `name`) VALUES (1, 'yahoo'), (2, '楽天'), (3, '電話'), (4, 'メール'), (5, 'その他'); --------------店舗-------------- CREATE TABLE IF NOT EXISTS `shop` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; INSERT INTO `shop` (`id`, `name`) VALUES (1, '新宿'), (2, '池袋'), (3, '渋谷'), (4, '博多'), (5, '梅田'); --------------来客数-------------- CREATE TABLE IF NOT EXISTS `raikyakusuu` ( `id` int(11) NOT NULL AUTO_INCREMENT, `date` date DEFAULT NULL, `shop_id` int(2) DEFAULT NULL, `media_id` int(2) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8; INSERT INTO `raikyakusuu` (`id`, `date`, `shop_id`, `media_id`) VALUES (1, '2013-11-01', 1, 1), (2, '2013-11-01', 1, 1), (3, '2013-11-01', 1, 2), (4, '2013-11-01', 4, 4), (5, '2013-11-01', 1, 2), (6, '2013-11-02', 3, 1), (8, '2013-11-02', 3, 4), (9, '2013-11-02', 2, 2), (10, '2013-11-02', 2, 4), (11, '2013-11-03', 1, 4), (12, '2013-11-03', 3, 1), (13, '2013-11-05', 4, 3), (14, '2013-11-05', 1, 3), (15, '2013-11-06', 2, 2), (16, '2013-11-06', 3, 3), (17, '2013-11-06', 1, 5); select DATE_FORMAT(r.`date`,'%d日') as DayTime, count(*) as cnt, s.`name` as s_name, m.`name` as m_name from raikyakusuu r LEFT JOIN shop s ON s.`id` = r.`shop_id` LEFT JOIN media m ON m.`id` = r.`media_id` WHERE DATE_FORMAT(r.`date`, '%Y-%m') = '2013-11' GROUP BY DayTime, m.`name` 上記のセレクト文で取れた結果をPHPにて 新宿 媒体 |01日|02日|03日|04日|05日|06日|07日|08日|・・・ yahoo | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 楽天 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 電話 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | メール | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | その他 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 池袋 媒体 |01日|02日|03日|04日|05日|06日|07日|08日|・・・ yahoo | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 楽天 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 電話 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | メール | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | その他 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 渋谷 媒体 |01日|02日|03日|04日|05日|06日|07日|08日|・・・ yahoo | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 楽天 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 電話 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | メール | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | その他 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | といったようにtableにて表示を考えておりますが、 うまくだせずに困っております。 条件といたしましては、 結果で取れていない媒体、日付も表示させ、cntには0と表示させたいです。 お分かりの方がいらっしゃいましたらご教示お願いいたします。 端折らせていただいている部分も御座いますが、宜しくお願いいたします。

    • ベストアンサー
    • PHP