好吧,我们有一个数据库,它的表列布局不太好,适合一家在线运作的小型新闻机构。目前,改变布局是不可能的;所以,我专注于查询。
网页需要一个"访客"作者列表。每个列表项应包含:
- 作者形象(作者)
- 作者姓名(作者)
- 他/她写的最后一篇文章的标题(新闻)
- 该文章的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
的速度。