【问题标题】:Multiple queries ordered by date created按创建日期排序的多个查询
【发布时间】:2017-05-18 07:07:08
【问题描述】:

我们需要按日期列出和排序几个事件。事件存储在多个表中,并由多个查询选择。我们不能使用 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
        }
      }
    }
  }
}

使用此解决方案将对我们的数据库进行数千次查询,所以我们的问题是 - 能否以更好的方式完成?

希望收到你们的来信...谢谢!

【问题讨论】:

  • order 是一个保留字,所以上面的内容并不完全正确。
  • 哦,但这只是一个例子。我们实际上使用“ordre”,这是挪威语的订单。上面的代码工作正常,只是我认为这是更好的方法。
  • 您可以使用联合,您只需在引用表的查询中创建具有较少列的虚拟列。另一种可能性是定义一组公共列并将它们作为每个查询中的列,然后对于那些具有多个基本列的列,使用 concat 为该表唯一的列创建具有名称/值对的单个列。您甚至可以将其格式化为 JSON 以使它们更容易爆炸。
  • 嗯..虽然有点乱,但由于单个查询,也许是更好的解决方案?

标签: php mysql optimization


【解决方案1】:

** 添加括号。否则,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`

【讨论】:

  • 括号似乎没有任何作用,但感谢您提供有关 UNION ALL 的提示。你能解释一下你的最后一个代码吗?有什么比使用 BETWEEN 更好的呢。
猜你喜欢
  • 2017-08-05
  • 2015-03-31
  • 2021-01-14
  • 2014-06-04
  • 2015-05-08
  • 2012-02-10
  • 1970-01-01
  • 1970-01-01
  • 2021-08-13
相关资源
最近更新 更多