我被困在一个巨大的问题上,我将在下面的查询中说。这里j5代表星期五,j6代表星期六(1到7 …星期日至星期一)。
j5
j6
如您所知,公交车有不同的时间表,具体取决于一周中的时间。在这里,我服用后未来5个车次出发25:00:00上cal (j5)和/或后01:00:00上cal2 (j6)。公交车时刻表是这样构建的:
25:00:00
cal (j5)
01:00:00
cal2 (j6)
如果是凌晨1点,那么当前的公交时间是25点,凌晨2点是26点…就可以了。因此,如果我想在凌晨1点之后今天出发,那么“公共汽车”的一天即将结束,我可能只会得到2-3。为了解决这个问题,我想添加第二天的下一个出发日期(这里是星期五之后的星期六)。但是第二天就像世界上每一天一样从00开始。
因此,我想做的是:j5在25:00:00之后获得星期五的所有下次旅行。如果我没有5,则在01:00:00(因为25:00:00 = 01:00:00)之后的星期六获得全部n次旅行。
示例:我在星期五的25:16:00、25:46:00和26:16:00出发。现在是3点。我想第二天再进行2次出发,所以最后我得到5点,就像这样04:50:00和05:15:00。因此,从X站出发的下一趟旅程是:25:16:00(星期五),25:46:00(星期五),26:16:00(星期五),04:50:00(星期六),05:15:00 (周六)。
我在对两种结果进行排序时遇到问题trips.trip_departure。
trips.trip_departure
我知道这可能很复杂,对我来说很难解释,但是…无论如何。有问题我在这里。在此先多谢!
PS:使用MySQL 5.1.49和PHP 5.3.8。PS2:我想避免在PHP中执行多个查询,因此无论如何我都希望在一个查询中执行此操作。
SELECT trips.trip_departure, trips.trip_arrival, trips.trip_total_time, trips.trip_direction FROM trips, trips_assoc, ( SELECT calendar_regular.cal_regular_id FROM calendar_regular WHERE calendar_regular.j5 = 1 ) as cal, ( SELECT calendar_regular.cal_regular_id FROM calendar_regular WHERE calendar_regular.j6 = 1 ) as cal2 WHERE trips.trip_id = trips_assoc.trip_id AND trips.route_id IN (109) AND trips.trip_direction IN (0) AND trips.trip_period_start <= "2011-11-25" AND trips.trip_period_end >= "2011-11-25" AND ( ( cal.cal_regular_id = trips_assoc.calendar_id AND trips.trip_departure >= "25:00:00" ) OR ( cal2.cal_regular_id = trips_assoc.calendar_id AND trips.trip_departure >= "01:00:00" ) ) ORDER BY trips.trip_departure ASC LIMIT 5
编辑 表结构:
表格calendar_regular
j1表示星期日,j7表示星期一)。
`cal_regular_id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT, `j1` tinyint(1) NOT NULL COMMENT 'Lundi', `j2` tinyint(1) NOT NULL COMMENT 'Mardi', `j3` tinyint(1) NOT NULL COMMENT 'Mercredi', `j4` tinyint(1) NOT NULL COMMENT 'Jeudi', `j5` tinyint(1) NOT NULL COMMENT 'Vendredi', `j6` tinyint(1) NOT NULL COMMENT 'Samedi', `j7` tinyint(1) NOT NULL COMMENT 'Dimanche', PRIMARY KEY (`cal_regular_id`), KEY `j1` (`j1`), KEY `j2` (`j2`), KEY `j3` (`j3`), KEY `j4` (`j4`), KEY `j5` (`j5`), KEY `j6` (`j6`), KEY `j7` (`j7`)
数据 :
cal_regular_id j1 j2 j3 j4 j5 j6 j7 1 0 0 0 0 1 0 0 2 0 0 0 1 1 0 0 3 1 1 1 1 1 0 0 4 0 0 0 0 0 1 0 5 0 0 0 0 0 0 1
x天有一些可用的公共汽车,它是一个表,用于定义一周中的何时…分配给trip_assoc表。
行程表
`agency_id` smallint(5) unsigned NOT NULL, `trip_id` binary(16) NOT NULL, `trip_period_start` date NOT NULL, `trip_period_end` date NOT NULL, `trip_direction` tinyint(1) unsigned NOT NULL, `trip_departure` time NOT NULL, `trip_arrival` time NOT NULL, `trip_total_time` mediumint(8) NOT NULL, `trip_terminus` mediumint(8) NOT NULL, `route_id` mediumint(8) NOT NULL, `shape_id` binary(16) NOT NULL, `block` binary(16) DEFAULT NULL, KEY `testing` (`route_id`,`trip_direction`), KEY `trip_departure` (`trip_departure`)
trips_assoc表
`agency_id` tinyint(4) NOT NULL, `trip_id` binary(16) NOT NULL, `calendar_id` smallint(6) NOT NULL, KEY `agency_id` (`agency_id`), KEY `trip_id` (`trip_id`,`calendar_id`)
首先, _ 永远不要 让外部实体指定非唯一的连接列。它们可能(具有授权/认证)可以指示 _唯一 的(例如确定性GUID值)。否则,他们将在某个地方指定一个 自然 键,并且您的数据库会自动分配要加入的行ID。另外,除非您要处理未索引行上的 大量 联接(数十个),否则性能将远不及在其他地方处理它时的麻烦。
因此,从外观上看,您正在存储多家公司的公交车时刻表(类似于google,这是获取公共交通路线的必经之路)。 这是我要如何处理:
您将需要一个日历文件。这对于所有业务场景都是有用的,但是在这里将非常有用(请注意:不要在其中添加任何与路由相关的信息)。
修改agency表以控制联接键。代理商 无法 指定其ID,只能指定其名称(或一些类似的标识符)。如下所示就足够了:
agency
============= id - identity, incrementing name - Externally specified name, unique
修改route表以控制联接键。代理只能指定其(可能是非唯一的) 自然 键,因此我们需要用于联接的 代理 键:
route
============== id - identity, incrementing agency_id - fk reference to agency.id route_identifier - natural key specified by agency, potentially non-unique. - required unique per agency_id, however (or include variation for unique) route_variation - some agencies use the same routes for both directions, but they’re still different. route_status_id - fk reference to route_status.id (potential attribute, debatable)
请注意,路线表实际上不应列出路线上的 停靠站 -唯一的目的是控制哪个代理商拥有哪个路线。
创建一个location或address表。这将使您受益匪浅,因为大多数运输公司倾向于在同一地点放置多条路线:
location
address
============= id - identity, incrementing address - there are multiple ways to represent addresses in a database. - if nothing else, seperating the fields should suffice lat/long - please store these properly, not as a single column. - two floats/doubles will suffice, although there are some dedicated solutions.
此时,您有两个选择来处理路线上的停靠点:
stop
================ id - identity, incrementing route_id - fk reference to route.id location_id - fk reference to location.id departure - Timestamp (date and time) when the route leaves the stop.
这当然会很快变得很大,但是使处理假期计划变得容易。
2. 定义一个`schedule`表集和一个`schedule_override`表集: schedule =================== id - identity, incrementing route_id - fk reference to route.id start_date - date schedule goes into effect. schedule_stop =================== schedule_id - fk reference to schedule.id location_id - fk reference to location.id departure - Time (time only) when the route leaves the stop dayOfWeek - equivalent to whatever is in calendar.nameOfDay - This does not have to be an id, so long as they match schedule_override =================== id - identity, incrementing route_id - fk reference to route.id effective_date - date override is in effect. Should be listed in the calendar file. reason_id - why there's an override in effect. schedule_override_stop =========================== schedule_override_id - fk reference to schedule_override.id location_id - fk reference to location.id departure - time (time only) when the route leaves the stop
有了这些信息,我现在可以获得所需的信息:
SELECT FROM agency as a JOIN route as b ON b.agency_id = a.id AND b.route_identifier = :(whatever 109 equates to) AND b.route_variation = :(whatever 0 equates to) JOIN (SELECT COALESCE(d.route_id, j.route_id) as route_id, COALESCE(e.location_id, j.location_id) as location_id, COALESCE(TIMESTAMP(c.date, e.departure), TIMESTAMP(c.date, j.departure)) as departure_timestamp FROM calendar as c LEFT JOIN (schedule_override as d JOIN schedule_override_stop as e ON e.schedule_override_id = d.id) ON d.effective_date = c.date LEFT JOIN (SELECT f.route_id, f.start_date g.dayOfWeek, g.departure, g.location_id, (SELECT MIN(h.start_date) FROM schedule as h WHERE h.route_id = f.route_id AND h.start_date > f.start_date) as end_date FROM schedule as f JOIN schedule_stop as g ON g.schedule_id = f.id) as j ON j.start_date <= c.date AND j.end_date > c.date AND j.dayOfWeek = c.dayOfWeek WHERE c.date >= :startDate AND c.date < :endDate) as k ON k.route_id = b.id AND k.departure_timestamp >= :leaveAfter JOIN location as m ON m.id = k.location_id AND m.(location inforation) = :(input location information) ORDER BY k.departure_timestamp ASC LIMIT 5
这将列出从指定位置出发的所有出发点的清单,对于给定的路线,在startDate和之间endDate(不包括),在leaveAfter时间戳之后。语句(等效)在DB2上运行。它获取时间表的更改,节假日的替代等。
startDate
endDate
leaveAfter