优化foreach内部的SQL查询

问题描述 投票:0回答:1

我需要帮助优化我构建的循环日历的以下查询。

如果用户未能完成指定日期的所有任务 < 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(每周、偶数周、奇数周)

mysql foreach query-optimization
1个回答
1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.