如何从按时间排序的多个表中获取最后30个项目?

时间:2011-05-18 19:00:06

标签: php mysql sql

我有3张桌子可以从中获取信息:

  • 制品
  • 帖子
  • 图片

所有这些表都有'created_at'列。

我想通过created_at列抛出sql查询来获取最后30个项目, 在最坏的情况下,我将不得不从任何表中弹出30个项目,并通过PHP代码从数组中订购。

4 个答案:

答案 0 :(得分:1)

这样的事情:

(SELECT * FROM articles)
UNION 
(SELECT * FROM posts)
UNION 
(SELECT * FROM pictures)
ORDER BY created_at DESC 
LIMIT 30

这是未经测试的,但应该有效。确保将“*”更改为您正在使用的任何字段。

答案 1 :(得分:1)

以过去的答案为基础,并在此处添加一些优化:

SELECT created_at, tbl, id, name, author_id FROM
  (SELECT created_at, "articles" as tbl, id, name, author_id 
   FROM `articles` ORDER BY created_at DESC LIMIT 30
   UNION 
  SELECT created_at, "posts" as tbl, id, name, author_id 
   FROM `posts` ORDER BY created_at DESC LIMIT 30
   UNION 
  SELECT created_at, "pictures" as tbl, id, name, author_id 
   FROM `pictures` ORDER BY created_at DESC LIMIT 30
  )
ORDER BY created_at DESC LIMIT 30;

FWIW - 这是未经测试的,可能包含愚蠢的错误。

我首先假设created_at已在所有三个表上编入索引。 我还要限制每个表只返回'最后30个项',所以我们没有订购一个可能很大的派生表(我们无法索引)。

因此,派生表上的最终'order by'保证订购< = 90行 比订购3个表的总联合要好得多。

答案 2 :(得分:0)

类似的东西:

SELECT * FROM
  (SELECT * FROM articles UNION SELECT * FROM posts UNION SELECT * FROM pictures)
ORDER BY created_at DESC LIMIT 30

几乎可以肯定,您需要将*替换为您要选择的两个表共有的字段列表(例如,ID),并且可能需要识别它的对象类型(例如,{ {1}})

小心放置SELECT a, b, 'article' AS item_type条款的位置。理想情况下,您可以在每个内部选择上放置一个以限制其中包含的对象,而不是在外部放置一个必须等​​待整个WHERE操作首先执行的WHERE。{ / p>

答案 3 :(得分:0)

我会选择:

Select top 30 * from
(select acticles.created_at, ID 
from articles 
UNION
select posts.created_at, ID 
from posts 
UNION
select pictures.created_at, ID 
from pictures
ORDER BY 1)