CREATE TABLE EPR (
`holding_id` bigint(30) NOT NULL AUTO_INCREMENT,
`event_id` bigint(20) unsigned NOT NULL,
`place_id` bigint(20) unsigned NOT NULL,
`rule_id` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`holding_id`),
UNIQUE KEY `compound` (`place_id`,`event_id`,`rule_id`),
KEY `FK_Places-Company Events-Rules_Events_event_id` (`event_id`),
KEY `FK_Places-Company Events-Rules_Places_place_id` (`place_id`),
KEY `FK_Places-Company Events-Rules_Rules_rule_id` (`rule_id`),
CONSTRAINT `FK_Places-Company Events-Rules_Events_event_id`
FOREIGN KEY (`event_id`) REFERENCES `Events` (`event_id`) ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `FK_Places-Company Events-Rules_Rules_rule_id`
FOREIGN KEY (`rule_id`) REFERENCES `Rules` (`rule_id`) ON DELETE CASCADE ON
UPDATE CASCADE,
CONSTRAINT `fk_place_id_pcerc` FOREIGN KEY (`place_id`)
REFERENCES `Places` (`place_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB CHARSET=latin1;
存储功能
有两个存储函数。开始 and GETENDS。参数:rule_id、timestamp、curtimestamp。Timestamp是当天的unix时间戳,curtimestamp是当天开始的unix时间戳。
这些函数的工作原理如下。对于每个规则,它们返回规则的开头(开始)和结束(结束)。如果规则不可重复,则返回start_date and end_date存储在规则表中。如果规则是可重复的,他们会构建begins and endsRegularRules 表中最接近的非空 day_start/day_end 的值。例如,有一个事件有 2 个规则。第一个不可重复开始start_timestamp并结束end_timestamp。第二个是可重复的,并且只有两个非空字段:mon_start = 36000 and mon_end = 64800. GETBEGINS将转向mon_start在unix时间戳中,基于当前unix时间戳和当天开始的当前unix时间戳。GETBEGINS工作原理类似。如有需要,将提供这些功能的代码。
SELECT
epr.event_id,
epr.place_id,
epr.rule_id,
(6371 * ACOS(COS(RADIANS(latpoint)) * COS(RADIANS(latitude)) *
COS(RADIANS(longitude) - RADIANS(longpoint)) + SIN(RADIANS(latpoint)) *
SIN(RADIANS(latitude)))) AS distance,
p.latitude,
p.longitude,
GETBEGINS(r.rule_id, curstamp, timestamp) AS begins,
GETENDS(r.rule_id, curstamp, timestamp) AS ends,
MIN(ABS(GETBEGINS(r.rule_id, curstamp, timestamp) - timestamp)) AS
time_min
FROM
Events e
INNER JOIN
EPR epr ON e.event_id = epr.event_id
INNER JOIN
Places p ON epr.place_id = p.place_id
INNER JOIN
Rules r ON epr.rule_id = r.rule_id
WHERE
r.end_date >= timestamp
AND latitude BETWEEN latpoint - (r / 111.045) AND latpoint + (r /
111.045)
AND longitude BETWEEN longpoint - (r / (111.045 *
COS(RADIANS(latpoint)))) AND longpoint + (r / (111.045 *
COS(RADIANS(latpoint))))
AND e.isPublic = 1
GROUP BY epr.place_id
如主题中所述,此查询混合返回值。更具体地说,它与 place_id 组匹配错误的rule_id,begins,ends。
而且这个查询的性能很差。表的大小:事件 - 3000 行,地点 - 8000 行,规则 18000 行,EPR - 15000 行。使用索引提示时,这些查询大约需要 1.8 秒(use index compound) 和 1.2 没有一个。不使用索引提示查询会进行全表扫描。
我读过了官方 mysql 文档 http://dev.mysql.com/doc/refman/5.0/en/example-maximum-column-group-row.html关于这个主题。然而,由于用户计算的值,他们的解决方案并不适用(GETBEGINS and GETENDS).
Question
中提供的查询预期查询部分由于方式存在分组最小值问题mysql 处理分组依据 http://dev.mysql.com/doc/refman/5.6/en/group-by-handling.html。那么可能的解决方案是使函数 GET BEGINS 和 GETENDS 用户定义的聚合函数这样 mysql 可能会返回适当的结果吗?这个解决方案合乎逻辑吗?遗嘱制作功能GETBEGINS and GETENDS汇总帮助?在这种情况下mysql会返回适当的数据吗?
结论
欢迎对所提供的解决方案、新解决方案、索引和数据库架构发表评论。
不保证分组最大值有效。事实上,MariaDB 破坏了它,但提供了一个设置来恢复它。这就是我指的:
SELECT *
FROM
( SELECT ... ORDER BY ... )
GROUP BY ...