首先获取粘贴帖子的SQL查询

时间:2012-05-30 00:35:07

标签: sql postgresql

我正在建立博客,但我遇到了问题。应该有一些粘性帖子。我想要的只是获得粘贴帖子,然后是其余的。

一个有效的查询是

select * from 

(
(select *,true as st from blog where "stickyUntil" > current_timestamp) 
UNION  all
(SELECT *,false as st from blog where "stickyUntil" < current_timestamp  or "stickyUntil" is null  ) 
) q 


order by st desc, "stickyUntil" DESC ,publish DESC OFFEST x LIMIT z

另一个更简单的查询是workz

select * from blog order by case when "stickyUntil" > current_timestamp then "stickyUntil" end desc nulls last, publish desc;

但这会迫使200,000行在内存中排序不是很快..

有没有办法优化它?

使用两个单独的查询会更好吗? 感谢

3 个答案:

答案 0 :(得分:3)

我会使用CASE语句来避免表格的两次传递:

select *, 
   CASE 
   WHEN "stickyUntil" > current_timestamp THEN true
   ELSE false
   END as st
FROM blog
ORDER BY st DESC ,publish DESC OFFEST x LIMIT z

Postgres支持在计算字段上创建INDEX,这对此有帮助,但存在限制:

  

索引定义中使用的所有函数和运算符必须是&#34; immutable&#34;,   也就是说,他们的结果必须仅依赖于他们的论点,而不是任何依据   外部影响(例如另一张桌子的内容或当前时间)。

因此您无法索引 st 计算。如果 st 的计算不需要太精确,则另一个选项是将 st 字段添加到表中:

ALTER TABLE blog
ADD COLUMN st boolean default true

INDEX st 作为常规列:

CREATE INDEX sti ON blog(st)

并定期运行:

UPDATE blog
SET st = false
WHERE st = true
AND "stickyUntil" < current_timestamp

但是进行更新的轮询过程远比直接查询更具吸引力。这只有在您的查询非常慢或者博客表的大量读取时才有意义。

答案 1 :(得分:1)

我认为你最好不要运行两个查询,一个用于粘贴帖子,另一个用于其他查询。

SQL不保证结果的排序,没有明确的顺序。尽管UNION ALL的结果似乎正确,但您无法保证。这在多线程环境中变得更加明显,在这种环境中,您不知道哪个线程将首先完成读取数据并开始返回结果。

最有效的解决方法是将其作为两个不同的查询。

答案 2 :(得分:0)

select * 
from blog
order by 
    coalesce("stickyUntil", '1901-01-01'::date) < current_timestamp, 
    publish DESC 
OFFSET x LIMIT z