0

我有一张名为预订的表格,其中包含以下字段:

`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(150) NOT NULL,
`begin_time` datetime NOT NULL,
`end_time` datetime NOT NULL,
`node_id` int(11) NOT NULL,
PRIMARY KEY (`id`)

我希望显示给定时间段内的预订统计信息(比如 $from - $until,来自 php 的值)。用户在每次预订时预订一个节点。有许多可以预订的节点,我使用以下查询按日期显示预订统计信息。

SELECT DATE(begin_time) `Date`, count(id) as reservations
FROM reservation
WHERE begin_time > '" . $from . "'
AND end_time < '" . $until . "'
GROUP BY Date"

现在我想统计一天中哪个时间段更活跃。一天的 24 小时被分成 48 个 30 分钟的时段。在我的表中,所有 begin_date 和 end_date 值都是整数,例如 2011-04-11 20:00:00 或 2011-04-11 14:30:00。预订的持续时间可以是 30 分钟、60 分钟等,最长可达 4 小时。

我希望我的统计数据采用以下格式(或多或少)

    Time slot       | reservations
----------------------------------
00:00:00 - 00:30:00 |     23
00:30:00 - 01:00:00 |     12
01:00:00 - 01:30:00 |     20
01:30:00 - 02:00:00 |     66
02:00:00 - 02:30:00 |     12
                and so on

你能帮我处理 SQL 查询吗?

编辑:我现在看到 PostgreSQL 有一些范围类型和运算符,例如 <@ (range is contains by) documentation here。这是否意味着如果我使用 Postgres,我的查询会更容易?MySQL有类似的东西吗?

编辑2:谢谢你,汤姆。实际上,我更改了您的答案,Date从 select 子句和 group by 子句中删除了 DATE(begin_time) AS ,因为我想查看在很多天的时间段内一天中哪些时间最活跃。而且我可以忍受 1 小时的粒度而不是 30 分钟。但我想问你你的第一句话到底是什么意思。如果预订从 01:00:00 开始并在 03:00:00 结束,我实际上确实希望它在两个时间段都被计算在内。

4

1 回答 1

1

在我的表中,所有 begin_date 和 end_date 值都是整数,例如 2011-04-11 20:00:00 或 2011-04-11 14:30:00

除非你也有像2011-04-11 14:15:00你想要的结果那样的时间,步长为 30 分钟没有多大意义,除非你想计算一些预订两次。

除了在 MySQL 中,它会是这样的:

SELECT 
DATE(begin_time) AS `Date`,
CASE 
WHEN TIME(begin_time) >= '00:00:00' AND TIME(begin_time) < '01:00:00' THEN '00:00:00 - 01:00:00' 
WHEN TIME(begin_time) >= '01:00:00' AND TIME(begin_time) < '02:00:00' THEN '01:00:00 - 02:00:00' 
/*...and so on...*/
END AS `TimeSlot`,
COUNT(id) as reservations
FROM reservation
WHERE begin_time > '" . $from . "'
AND end_time < '" . $until . "'
GROUP BY `Date`, `TimeSlot`

我将其设置为 1 小时的时间段,并添加了要分组的日期。

其实,傻我,现在想想,当你有正好一小时的时间段时,你也可以这样做:

SELECT 
DATE(begin_time) AS `Date`,
HOUR(begin_time) AS `TimeSlot`,
COUNT(id) as reservations
FROM reservation
WHERE begin_time > '" . $from . "'
AND end_time < '" . $until . "'
GROUP BY `Date`, `TimeSlot`

更新:

SELECT 
CASE 
WHEN TIME(begin_time) BETWEEN '00:00:00' AND '01:00:00' OR TIME(end_time) BETWEEN '00:00:00' AND '01:00:00' THEN '00:00:00 - 01:00:00' 
WHEN TIME(begin_time) BETWEEN '01:00:00' AND '02:00:00' OR TIME(end_time) BETWEEN '01:00:00' AND '02:00:00' THEN '01:00:00 - 02:00:00' 
/*...and so on...*/
END AS `TimeSlot`,
COUNT(id) as reservations
FROM reservation
WHERE begin_time > '" . $from . "'
AND end_time < '" . $until . "'
GROUP BY `TimeSlot`
于 2013-04-09T09:17:29.377 回答