ORDER BY来自main和子查询的替代值

时间:2015-01-30 20:11:51

标签: sql postgresql sql-order-by postgresql-9.3

现在我的查询看起来像这样:

SELECT id 
FROM post_table post
WHERE post.post_user_id = user_id
ORDER BY (SELECT max(comment_created_date) 
          FROM comments_table WHERE comments_post_id = post.id) DESC,
 post.post_created_date DESC

我对此查询的想法是,它会订购一系列帖子,如此

Post 1:
    created Date: Jan 1 2015
    comments : []

Post 2:
     created Date: Jan 5 2015
     comments : []

Post 3:
     created Date : December 1 2014
     comments: [
         0: Created Date: Jan 6 2015
      ]

因此,在这种情况下,将返回帖子的顺序是

Post 3,Post 2,Post 1

因为Post 3的评论比任何其他帖子更新,Post 2是在Post 1之前创建的。

但是当我运行查询时,帖子仍然按其创建日期排序,查询似乎没有考虑创建日期的评论。

2 个答案:

答案 0 :(得分:2)

它应该像这样工作:

SELECT id 
FROM   post_table p
WHERE  post_user_id = $user_id  -- this is your input parameter
ORDER  BY GREATEST(
   (
   SELECT max(comment_created_date) 
   FROM   comments_table
   WHERE  comments_post_id = p.id
   )
 , post_created_date) DESC NULLS LAST;

如果日期列可以为NULL,则需要添加NULLS LAST

如果评论只能晚于帖子(有意义),则可以使用COALESCE代替GREATEST

更清洁的替代方案(可能更快,也可能不会更快,具体取决于数据分布):

SELECT id 
FROM   post_table p
LEFT   JOIN  (
   SELECT comments_post_id AS id, max(comment_created_date) AS max_date
   FROM   comments_table
   GROUP  BY 1
   ) c USING (id)
WHERE  post_user_id = $user_id
ORDER  BY GREATEST(c.max_date, p.post_created_date) DESC NULLS LAST;

由于你有第9.3页,你也可以使用LATERAL加入。可能更快:

SELECT id 
FROM   post_table p
LEFT   JOIN  LATERAL (
   SELECT max(comment_created_date) AS max_date
   FROM   comments_table
   WHERE  comments_post_id = p.id
   GROUP  BY comments_post_id
   ) c ON TRUE
WHERE  post_user_id = $user_id
ORDER  BY GREATEST(c.max_date, p.post_created_date) DESC NULLS LAST;

答案 1 :(得分:0)

我建议的另一件事,如果这将是一个受到重创的查询,是在'date_last_commented'的post_table上创建一个计算列 并使用触发器更新注释表的任何插入或更新。

然后你可以运行简单的查询:

SELECT id 
FROM post_table post
WHERE post.post_user_id = user_id
ORDER BY post.date_last_commented DESC nulls last, post.post_created_date DESC
;