我需要帮助优化我构建的循环日历的以下查询。
如果用户未能完成指定日期的所有任务 < today, I want to show a reminder which states the date and title of the task. Since the calendar uses recurrent events the same ID can be targeted multiple times.
这是我在 foreach 中使用的查询,它获取当前活动处于活动状态的所有日期。
这是我当前的设置,可以工作,但速度很慢。
其他字符串解释:
$today=date("Y-m-d");
$parts = explode($separator, $datespan);
$dayForDate2 = date("l", mktime(0, 0, 0, $parts[1], $parts[2], $parts[0]));
$week2 = strtotime($datespan);
$week2 = date("W", $week2);
if($week2&1) { $weektype2 = "3"; } # Odd week 1, 3, 5 ...
else { $weektype2 = "2"; } # Even week 2, 4, 6 ...
查询#1:
$query1 = "SELECT date_from, date_to, bok_id, kommentar
FROM bokningar
WHERE bokningar.typ='2'
AND date_from < '".$today."'";
使 foreach 向前移动一天的函数...
function date_range($first, $last, $step = '+1 day', $output_format = 'Y-m-d' )
{
$dates = array();
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last ) {
$dates[] = date($output_format, $current);
$current = strtotime($step, $current);
}
return $dates;
}
对于每个:
foreach (date_range($row['date_from'], $row['date_to'], "+1 day", "Y-m-d")
as $datespan)
if ($datespan < $today)
查询#2:
$query2 = "
SELECT bok_id, kommentar
FROM bokningar b
WHERE b.typ='2'
AND b.bok_id='".$row['bok_id']."'
AND b.weektype = '1'
AND b.".$dayForDate2." = '1'
AND NOT EXISTS
(SELECT t.tilldelad, t.bok_id
FROM tilldelade t
WHERE t.tilldelad = '".$datespan."'
AND t.bok_id='".$row['bok_id']."')
OR b.typ='2'
AND b.bok_id='".$row['bok_id']."'
AND b.weektype = '".$weektype2."'
AND b.".$dayForDate2." = '1'
AND NOT EXISTS
(SELECT t.tilldelad, t.bok_id
FROM tilldelade t
WHERE t.tilldelad = '".$datespan."'
AND t.bok_id='".$row['bok_id']."')";
b.weektype 为 1,2 或 3(每周、偶数周、奇数周)
bokningar
需要INDEX(typ, date_from)
除了今天计算 $,您还可以这样做
and date_from < CURDATE()
您是否为每个日期运行 $query2 ?那是多少天?您也许可以构建一个日期表,然后将其
JOIN
到 bokningar
,以在单个 SELECTs
中完成所有 SELECT
。
做
x AND y OR x AND z
时,先加上括号,明确哪个在先 AND 或 OR:(x AND y) OR (x AND z)
。然后使用布尔算术中的简单规则将其转换为更有效的表达式:x AND (y OR z)
(其中需要括号)。
EXISTS
的通常模式是EXISTS ( SELECT 1 FROM ... )
;无需列出列。
如果我没读错的话,唯一的区别在于测试
b.weektype
。所以WHERE
可以简单地
WHERE b.weektype IN ('".$weektype2."', '1')
AND ...
不需要 OR,因为它在
IN()
中有效。
tilldelade
需要 INDEX(tilldelad, bok_id)
,无论顺序如何。这应该会使 EXISTS(...)
运行得更快。
最后,
bokningar
需要 INDEX(typ, bok_id, weektype)
(任意顺序)。
需要改变和测试的东西很多。看看你能否完成这些事情。如果它仍然运行得不够快,请使用新代码开始一个新问题。请为这两个表添加
SHOW CREATE TABLE
。