按日期排序的多个查询

时间:2017-05-17 18:08:33

标签: php mysql optimization

我们需要列出几个事件并按日期排序。事件存储在多个表中,并由多个查询选择。我们不能使用union + order by,因为一个表可能有3-4列,而另一个表有大约20列。

我们提出了以下解决方案:

$stmt = $db->query("
  SELECT 'login' table, id, created
  FROM login
  WHERE date(created) BETWEEN 'somedate' AND 'somedate'
  UNION
  SELECT 'order' table, id, created
  FROM order
  WHERE date(created) BETWEEN 'somedate' AND 'somedate'
  UNION
  SELECT 'receipt' table, id, created
  FROM receipts
  WHERE date(created) BETWEEN 'somedate' AND 'somedate'
  ORDER BY created
");

while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    $sorted[] = array(
      "table" => $row['table'],
      "id" => $row['id']
    );
}

foreach (array_chunk($sorted, 5000) as $dataChunk) {
  foreach ($dataChunk as $row) {
    if ($row['table'] == "login") {
      $stmt = $db->query("
        SELECT some columns
        FROM logins
        WHERE id = ".$row['id']."
      ");
      $row_count = $stmt->rowCount();
      if ($row_count != '0') {
        while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
          do something
        }
      }
    }
    if ($row['table'] == "order") {
      $stmt = $db->query("
        SELECT some columns
        FROM logins
        WHERE id = ".$row['id']."
      ");
      $row_count = $stmt->rowCount();
      if ($row_count != '0') {
        while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
          do a lot here
        }
      }
    }
    if ($row['table'] == "receipt") {
      $stmt = $db->query("
        SELECT some columns
        FROM logins
        WHERE id = ".$row['id']."
      ");
      $row_count = $stmt->rowCount();
      if ($row_count != '0') {
        while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
          do something
        }
      }
    }
  }
}

使用这个解决方案,我们的数据库会有成千上万的查询,所以我们的问题是 - 这可以用更好的方式完成吗?

希望听到你们的意见......谢谢!

1 个答案:

答案 0 :(得分:0)

**添加括号。否则,ORDER BY仅适用于SELECT

( SELECT ... )
UNION ALL
( SELECT ... )
UNION ALL
( SELECT ... )
ORDER BY ...

**如果您希望删除它们并且想要删除它们(不一定基于您的代码),则明确指定UNION DISTINCT,或UNION ALL以获得速度。

**对于速度,如果你有INDEX(created)

WHERE created >= 'start...'
  AND created  < 'end...' + INTERVAL 1 DAY`