我有一个'Course'
表和一个'Event'
表。
我想拥有实际发生的所有课程,即它们不会被活动取消。
我通过对所有课程和脚本分析(基本上是一些循环)的简单请求完成了这个,但是这个请求需要一段时间,我相信太久了。我认为我想要的是一个查询,没有循环来优化这个请求。
以下是详细信息:
'Course' c
包含字段'date'
,'duration'
以及与'Grade'
表格的多对多关系'Event' e
包含字段'begin'
,'end'
,'break'
以及与'Grade'
表格的多对多关系e.break = 1
)欢迎任何帮助,
提前致谢,
PS:我正在使用mysql
编辑:表格详情
道菜的
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| date | datetime | NO | | NULL | |
| duration | time | NO | | NULL | |
| type | int(11) | NO | | NULL | |
+-----------+-------------+------+-----+---------+----------------+
+-------+---------------------+----------+------+
| id | date | duration | type |
+-------+---------------------+----------+------+
| 1 | 2013-12-10 10:00:00 | 02:00:00 | 0 |
| 2 | 2013-12-11 10:00:00 | 02:00:00 | 0 |
+-------+---------------------+----------+------+
- 活动
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| begin | datetime | NO | | NULL | |
| end | datetime | YES | | NULL | |
| break | tinyint(1) | NO | | NULL | |
+-------------+-------------+------+-----+---------+----------------+
+----+---------------------+---------------------+-------+
| id | begin | end | break |
+----+---------------------+---------------------+-------+
| 1 | 2013-12-10 00:00:00 | 2013-12-11 23:59:00 | 1 |
+----+---------------------+---------------------+-------+
-course_grade
+-----------+----------+
| course_id | grade_id |
+-----------+----------+
| 1 | 66 |
| 2 | 65 |
| 2 | 66 |
+-----------+----------+
-event_grade
+----------+----------+
| grade_id | event_id |
+----------+----------+
| 66 | 1 |
+----------+----------+
所以在这里,只有课程2应该出现,因为课程1只有一个年级,这个年级有一个事件。
答案 0 :(得分:0)
在开始解决方案之前,我先从'我会改变什么'开始:
您正在混合date
,datetime
,start
,end
和duration
,尝试仅使用一种逻辑(如果它是您的模型)即
事件/课程有开始和结束时间(或开始/持续时间)
持续时间应该(恕我直言)不是时间
尝试找到事件/课程的最小时间片(是否有1秒事件?或者是5'的粒度(即10:00,10:05,10:10等)是否有效折衷?< / p>
我的解决方案,一个不具学术性的prgmatic (听起来很有趣,但在我看到注释的simillar概率中确实有效)
创建一个表格(T_TIME_OF_DAY),其中包含所有从00:00,00:05,... 23:55
在有效且有用的范围内创建一个表(T_DAYS)(一年?)
如果您需要查看整整一年(和{&lt;> >>,请将它们称为时间点(即select date, time from T_DAYS,T_TIME_OF_DAY
无条件) - (天x次)300 * 24 * 12~100,000行5'对你来说没问题) - 那不是很多而且没有问题
下一步是加入适合你时间点的诅咒(并且行数降至&lt;&lt;&lt; 100.000)
如果你接下来将这些与你的活动加入(再次使用时间点),你应该得到你想要的。
simplyfied quarters of a day:
12 12 12 12 12 12 12 12
08 09 10 11 12 13 14 15
|...|...|...|...|...|...|...|...
grade 65 (C).............2..................
grade 66 (C).........1...2..................
grade 65 (E)................................
grade 66 (e)........1111..................
(注释:我使用这个逻辑来计算服务的可用性,关于他们每月/每年的停机时间,并且可以使用已经在时间点准备的数据进行显示)
答案 1 :(得分:0)
(第二个答案,因为它是一个完全不同的mor3标准方法)
我为你做了SQLFiddle
所以该怎么做:
那是一个解决方案:
第一步(记住)选择课程,成绩(让我们称之为C)
第二步(记住)选择事件,成绩(让我们称之为E)
和 - tada -
从C中选择全部,其中E中没有行具有相同的成绩和相同的日期(不知何故)和eventtype ='break'
所以你的解决方案:
select
id, date start_time, date+duration end_time, grade_id
from Course c join course_grade cg on c.id=cg.course_id
where not exists (
select grade_id, begin start_time, end end_time
from event_grade eg join event e on eg.event_id=e.id
where
eg.grade_id=cg.grade_id
and e.break=1
and
(
(e.begin<=c.date and e.end >=c.date+c.duration)
or e.begin between c.date and c.date+c.duration
or e.end between c.date and c.date+c.duration
)
)
我没注意优化这里