テーブル
各行は、特定の日付の特定の時間に放送されたビデオを表しています。1日あたり約1600本のビデオがあります。
CREATE TABLE `air_video` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`date` DATE NOT NULL,
`time` TIME NOT NULL,
`duration` TIME NOT NULL,
`asset_id` INT(10) UNSIGNED NOT NULL,
`name` VARCHAR(100) NOT NULL,
`status` VARCHAR(100) NULL DEFAULT NULL,
`updated` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE INDEX `date_2` (`date`, `time`),
INDEX `date` (`date`),
INDEX `status` (`status`),
INDEX `asset_id` (`asset_id`)
)
ENGINE=InnoDB
タスク
2つの条件があります。
- 各動画は1日24回以下で表示する必要があります。
- 各動画は72時間以内にローテーションする必要があります。
ローテーションとは、最初からビデオが最後に放送されたときまでの期間を意味します。
したがって、ユーザーが指定した日付範囲を指定して、これらの条件に違反するすべてのビデオを選択する必要があります。
結果は、日ごとおよびasset_id(ビデオID)ごとにグループ化する必要があります。例えば:
date asset_id name dailyCount rotationSpan
2012-04-27 123 whatever_the_name 35 76
2012-04-27 134 whatever_the_name2 39 20
2012-04-28 125 whatever_the_name3 26 43
クエリ
今までに私はこのクエリを書きました:
SELECT
t1.date, t1.asset_id, t1.name,
(SELECT
COUNT(t3.asset_id)
FROM air_video AS t3
WHERE t2.asset_id = t3.asset_id AND t3.date = t1.date
) AS 'dailyCount',
MIN(CONCAT(t2.date, ' ', t2.time)) AS 'firstAir',
MAX(CONCAT(t2.date, ' ', t2.time)) AS 'lastAir',
ROUND(TIMESTAMPDIFF(
MINUTE,
MIN(CONCAT(t2.date, ' ', t2.time)),
MAX(CONCAT(t2.date, ' ', t2.time))
) / 60) as 'rotationSpan'
FROM
air_video AS t1
INNER JOIN
air_video AS t2 ON
t1.asset_id = t2.asset_id
WHERE
t1.status NOT IN ('bumpers', 'clock', 'weather')
AND t1.date BETWEEN '2012-04-01' AND '2012-04-30'
GROUP BY
t1.asset_id, t1.date
HAVING
`rotationSpan` > 72
OR `dailyCount` > 24
ORDER BY
`date` ASC,
`rotationSpan` DESC,
`dailyCount` DESC
問題
- ユーザーが指定した日の範囲が大きいほど、クエリの完了にかかる時間が長くなります(1か月の範囲の場合は約9秒かかります)
lastAir
タイムスタンプは、特定の日付にビデオが放映された最新の時刻ではなく、完全に放映された最新の時刻です。