0

私の映画データベースでは、ユーザーは次のようなセッション テーブルにデータベースを入力できます。

id | time | movie_id

time は映画が再生される日時で、movie_id は映画テーブルに関連するキーです。

現在、再生中の映画が同じである連続した日を見つけようとしています。たとえば、表示できるようにしたい。

3/6/2013 - 7/6/2013
Iron Man 3   7pm
Second Movie 10pm
ETC...

8/6/2013
Iron Man 3   8pm

9/6/2013 - 11/6/2013
Iron Man 3   7pm
Second Movie 10pm

時間と連続した日数の両方を使用してグループ化する方法はありますか? 必要に応じて、テーブルを別の日付と時刻の値に変更できます。どんな助けでも大歓迎です。これが PHP でのみ達成可能である場合は、開始方法についてのアイデアもいただければ幸いです。

ありがとうございました。質問がある場合、またはこの質問が十分に明確でない場合は、質問してください。

4

1 に答える 1

1

まあ、それほどエレガントではありませんが、GROUP_CONCAT集計関数と変数を使用して、SELECT同様の連続した日をグループ化する実用的なソリューションです。

スキーマとサンプル データ セット:

CREATE TABLE movies (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  title CHAR(64) NOT NULL
);
CREATE TABLE schedule (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  time TIMESTAMP NOT NULL,
  movie_id INT NOT NULL
);
INSERT INTO movies (title) VALUES
  ('Iron Man 3'),
  ('Second Movie')
;
INSERT INTO schedule (time, movie_id) VALUES
  ('2013-06-03 19:00:00', 1),
  ('2013-06-03 22:00:00', 2),
  ('2013-06-04 19:00:00', 1),
  ('2013-06-04 22:00:00', 2),
  ('2013-06-05 19:00:00', 1),
  ('2013-06-05 22:00:00', 2),
  ('2013-06-06 19:00:00', 1),
  ('2013-06-06 22:00:00', 2),
  ('2013-06-07 19:00:00', 1),
  ('2013-06-07 22:00:00', 2),
  ('2013-06-08 20:00:00', 1),
  ('2013-06-09 19:00:00', 1),
  ('2013-06-09 22:00:00', 2),
  ('2013-06-10 19:00:00', 1),
  ('2013-06-10 22:00:00', 2),
  ('2013-06-11 19:00:00', 1),
  ('2013-06-11 22:00:00', 2),
  ('2013-06-13 19:00:00', 1),
  ('2013-06-13 22:00:00', 2)
;

クエリ:

SELECT
    DATE_FORMAT(min_date, '%e/%c/%Y') AS beg_date,
    DATE_FORMAT(max_date, '%e/%c/%Y') AS end_date,
    title,
    LOWER(TIME_FORMAT(time, '%l%p')) AS `movie_time`
  FROM
    (SELECT
        MIN(min_date) AS min_date,
        MAX(max_date) AS max_date,
        range_schedule
      FROM
        (SELECT
            @min_date :=
              IF(@range_schedule <=> day_schedule
                 AND days.date <=> ADDDATE(@max_date, 1),
                @min_date,
                days.date
              ) AS min_date,
            @max_date := days.date AS max_date,
            @range_schedule := days.day_schedule AS range_schedule
          FROM
            (
              SELECT DATE(time) AS `date`, GROUP_CONCAT(CONCAT(TIME(time), '-', movie_id) ORDER BY time) AS day_schedule
              FROM schedule
              GROUP BY DATE(time)
              ORDER BY DATE(time)
            ) AS days,
            (SELECT
              @min_date := '0000-00-00',
              @max_date := '0000-00-00',
              @range_schedule := NULL
            ) r
        ) days_of_ranges
      GROUP BY min_date, range_schedule
    ) ranges
    JOIN schedule ON DATE(schedule.time) = ranges.min_date
    JOIN movies ON movies.id = movie_id
  ORDER BY min_date, time
;

そして結果:

|  BEG_DATE |  END_DATE |        TITLE | MOVIE_TIME |
-----------------------------------------------------
|  3/6/2013 |  7/6/2013 |   Iron Man 3 |        7pm |
|  3/6/2013 |  7/6/2013 | Second Movie |       10pm |
|  8/6/2013 |  8/6/2013 |   Iron Man 3 |        8pm |
|  9/6/2013 | 11/6/2013 |   Iron Man 3 |        7pm |
|  9/6/2013 | 11/6/2013 | Second Movie |       10pm |
| 13/6/2013 | 13/6/2013 |   Iron Man 3 |        7pm |
| 13/6/2013 | 13/6/2013 | Second Movie |       10pm |

PHP で行う必要があるのは、最後の値BEG_DATEEND_DATE値を保存して現在の値と比較し、いつ範囲ヘッダーを出力するかを決定することだけです。

于 2013-06-03T13:21:00.357 に答える