ORDER BY 来自主查询和子查询的替代值
ORDER BY alternative values from main- and subquery
现在我有一个看起来像这样的查询:
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
]
所以在这种情况下,帖子的返回顺序是
Post3,Post2,Post1
因为Post3的评论比其他任何帖子都新,而Post2是在Post1之前创建的。
但是当我 运行 查询时,帖子仍然全部按创建日期排序,查询似乎没有考虑评论的创建日期。
它应该像这样工作:
SELECT id
FROM post_table p
WHERE post_user_id = $user_id -- this is your input parameter
ORDER BY <b>GREATEST(</b>
(
SELECT max(comment_created_date)
FROM comments_table
WHERE comments_post_id = p.id
)
, post_created_date<b>)</b> DESC NULLS LAST;
如果日期列可以为 NULL,您需要添加 NULLS LAST
。
- PostgreSQL sort by datetime asc, null first?
如果评论只能晚于帖子(有意义),您可以使用COALESCE
instead of 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;
因为你有 pg 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;
如果这是一个命中率很高的查询,我建议的另一件事是在 'date_last_commented'
的 post_table 上创建一个计算列
并使用触发器在评论 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
;
现在我有一个看起来像这样的查询:
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
]
所以在这种情况下,帖子的返回顺序是
Post3,Post2,Post1
因为Post3的评论比其他任何帖子都新,而Post2是在Post1之前创建的。
但是当我 运行 查询时,帖子仍然全部按创建日期排序,查询似乎没有考虑评论的创建日期。
它应该像这样工作:
SELECT id
FROM post_table p
WHERE post_user_id = $user_id -- this is your input parameter
ORDER BY <b>GREATEST(</b>
(
SELECT max(comment_created_date)
FROM comments_table
WHERE comments_post_id = p.id
)
, post_created_date<b>)</b> DESC NULLS LAST;
如果日期列可以为 NULL,您需要添加 NULLS LAST
。
- PostgreSQL sort by datetime asc, null first?
如果评论只能晚于帖子(有意义),您可以使用COALESCE
instead of 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;
因为你有 pg 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;
如果这是一个命中率很高的查询,我建议的另一件事是在 'date_last_commented'
的 post_table 上创建一个计算列
并使用触发器在评论 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
;