【问题标题】:Better way to do this subquery执行此子查询的更好方法
【发布时间】:2026-02-03 02:55:01
【问题描述】:

假设我有这个查询:

<?
     $qi = $db->prepare('SELECT one.id, one.Value, two.Name, three.nfid, temp.Name AS Alias
           FROM one
           INNER JOIN two ON one.fid = two.id
           LEFT OUTER JOIN three ON two.fid = three.fid
           LEFT OUTER JOIN (SELECT id,Name FROM two) AS temp ON three.nfid = temp.id
           WHERE one.rid = ?
           ORDER BY one.id ASC');
      $qi->execute( array( $id ) );
?>

表之间的连接是:

one 包含许多行,其中包含 one.Valueone.ridone.fid 字段。

fid 是到表 two 的连接,其中包含项目的 two.Name (one.fid = two.id)。

但有时该项目是另一个项目的别名,这就是表 three 存在的原因。它包含three.fidthree.newfid 字段,其中three.newfid = two.id(但对于另一个带有另一个two.Name 的项目)

查询应该从 one 中获取具有特定one.rid 的所有行并获取one.Valuetwo.Name,如果此one.fid 存在three.fid,则获取two.Namethree.newfid 并称之为别名。

有没有办法改进这个查询或以其他方式解决问题?也许重塑数据库的布局?目前速度很慢。此处的示例已被简化以使其更通用。

谢谢。

【问题讨论】:

  • 您使用哪个数据库引擎?有索引吗?
  • MySQL 是的,id、rid、fid 和 newfid 都被索引了。

标签: php mysql sql performance


【解决方案1】:

括号中的子查询强制MYSQL忽略它的索引,这使得它需要很长时间。最好直接加入两个作为临时工。只要你总是把两个.[field] 和 temp.[field] 放在一起,就可以很好地区分它们。

  SELECT one.id, one.Value, two.Name, three.nfid, temp.Name AS Alias
  FROM one
  INNER JOIN two ON one.fid = two.id
  LEFT OUTER JOIN three ON two.fid = three.fid
  LEFT OUTER JOIN two AS temp ON three.nfid = temp.id
  WHERE one.rid = ?
  ORDER BY one.id ASC

【讨论】:

  • 成功了!感谢您解释为什么它变慢了。