SQL:一个需要优化的稍微复杂的查询



好吧,我们有一个数据库,它的表列布局不太好,适合一家在线运作的小型新闻机构。目前,改变布局是不可能的;所以,我专注于查询。

网页需要一个"访客"作者列表。每个列表项应包含:

  • 作者形象(作者)
  • 作者姓名(作者)
  • 他/她写的最后一篇文章的标题(新闻)
  • 该文章的URI(新闻)

括号中是存储信息的表名。

在"作者"(40多条记录)中,相关列为:

  • 图像
  • 名称
  • 键入(我们将在此处查找值"Guest")
  • ASCII(存储"名称"值,但不包含非英文字符和空格)

"新闻"(28k+records)表基本上是一个所有新闻和文章都涌入的池。感兴趣的列是:

  • Id(主键:越高,越新)
  • 类别
  • 标题
  • URI

现在,"类别"有一大堆价值观;但是,如果特定记录是一篇文章,那么该列将包含"Authors"的"ASCII"(而不是其"Id")。

有一个PHP代码,"同时"为每个作者查询。当我看到它的时候,我想把它换掉。所以,我想,"嗯……如何一次搞定这些?"然后想出了这个:

-- Aliases are prefixed with 't' for tables and 'c' for columns.
SELECT
  tAu.Image, tAu.Name, tNw.Title, tNw.URI
FROM ( -- tAu & tNw
    SELECT * FROM ( -- tRc & Authors
        SELECT
          MAX(Id) cId, Category cCt -- Max Id for most recent
        FROM
          News
        GROUP BY
          cCt
    ) tRc -- table of categories with their most recent id's
    INNER JOIN
      Authors
    ON
      tRc.cCt = Authors.ASCII
    WHERE
      Authors.Type = 'Guest'
) tAu -- table of authors with their most recent id's
INNER JOIN
  News tNw
ON
  tAu.cId = tNw.Id -- merging authors with their latest article info

目前,此查询大约需要0.0364秒。也许没那么糟糕;但是,我很好奇这是否可以做得更好(因为这个查询从新闻中选择了两次)。

我不知道它是否更快,但稍微清理了一下查询,这可能有助于优化器:

SELECT
  Authors.Image,
  Authors.Name,
  News.Title,
  News.URI
FROM (
    SELECT
      MAX(Id) TopNewsId,
      Category
    FROM News
    GROUP BY Category
) TopNewsPerCats
INNER JOIN News     ON News.Id       = TopNewsPerCats.TopNewsId
INNER JOIN Authors  ON Authors.ASCII = TopNewsPerCats.Category
                   AND Authors.Type  = 'Guest'

News表应该有一个以( Category, Id)开头的索引,以加快内部SELECT GROUP BY的速度。

最新更新