Sql查询首先获取粘性帖子

Sql查询首先获取粘性帖子,sql,postgresql,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" i

我正在建立一个博客,我有一个问题。应该有一些粘帖。我只想先拿到粘帖,然后拿到其他的

一个有效的查询是

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
但这将迫使在内存中对200.000行进行排序,速度不是很快

有没有办法优化它

使用两个单独的查询是否更好? 谢谢

我想用一句话来避免两次过关:

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
ALTER TABLE blog
ADD COLUMN st boolean default true
Postgres支持在计算字段上创建一个有助于此处的,但有一个限制:

索引定义中使用的所有函数和运算符都必须是“不可变的”, 也就是说,他们的结果必须只取决于他们的论点,而决不取决于任何人 外部影响(如其他表的内容或当前时间)

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

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
ALTER TABLE blog
ADD COLUMN st boolean default true
st作为常规列:

CREATE INDEX sti ON blog(st)
并定期运行:

UPDATE blog
SET st = false
WHERE st = true
AND "stickyUntil" < current_timestamp
更新博客
设置st=false
其中st=true
和“粘性直到”<当前时间戳
但是,让一个轮询过程进行更新比直接查询的吸引力要小得多。只有当您的查询速度非常慢或者对blog表有大量读取时,这才有意义

我会用一句话来避免两次通过表格:

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
ALTER TABLE blog
ADD COLUMN st boolean default true
Postgres支持在计算字段上创建一个有助于此处的,但有一个限制:

索引定义中使用的所有函数和运算符都必须是“不可变的”, 也就是说,他们的结果必须只取决于他们的论点,而决不取决于任何人 外部影响(如其他表的内容或当前时间)

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

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
ALTER TABLE blog
ADD COLUMN st boolean default true
st作为常规列:

CREATE INDEX sti ON blog(st)
并定期运行:

UPDATE blog
SET st = false
WHERE st = true
AND "stickyUntil" < current_timestamp
更新博客
设置st=false
其中st=true
和“粘性直到”<当前时间戳

但是,让一个轮询过程进行更新比直接查询的吸引力要小得多。只有当您的查询速度非常慢或者对blog表有大量读取时,这才有意义

我认为您最好运行两个查询,一个用于粘性帖子,另一个用于其他帖子

SQL不保证结果的顺序,没有明确的order by。虽然工会的结果似乎都是对的,但你不能保证。这在多线程环境中变得更加明显,您不知道哪个线程将首先完成数据读取并开始返回结果


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

我认为最好运行两个查询,一个用于粘性帖子,另一个用于其他帖子

select * 
from blog
order by 
    coalesce("stickyUntil", '1901-01-01'::date) < current_timestamp, 
    publish DESC 
OFFSET x LIMIT z
SQL不保证结果的顺序,没有明确的order by。虽然工会的结果似乎都是对的,但你不能保证。这在多线程环境中变得更加明显,您不知道哪个线程将首先完成数据读取并开始返回结果

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

select*
select * 
from blog
order by 
    coalesce("stickyUntil", '1901-01-01'::date) < current_timestamp, 
    publish DESC 
OFFSET x LIMIT z
从博客 订购人 合并(“stickyUntil”,“1901-01-01”::日期)<当前时间戳, 发布说明 偏移量x极限z
选择*
从博客
订购人
合并(“stickyUntil”,“1901-01-01”::日期)<当前时间戳,
发布说明
偏移量x极限z

这没有按应有的方式排序。如果stickyUntil datetime已过,则发布只会起作用。。。我想知道是否有一种方法可以索引订单…(哎呀,刚刚注意到我的评论重复了您已经尝试过的CASE/NULLS方法。)您是对的。如果stickyUntil通过后发布顺序优先,则它将不起作用。我将更新答案以反映这一点。这些查询是否需要cornjob?我认为在每次选择之前运行更新查询应该更快(至少比完整表扫描更快),因为会有4-5个粘滞点,因此实际更新应该很少。这是真的吗?我想知道(stickyUntil,st)上的索引是否更好??这不是它应该的排序方式。如果stickyUntil datetime已过,则发布应该只起作用。。。我想知道是否有一种方法可以索引订单…(哎呀,刚刚注意到我的评论重复了您已经尝试过的CASE/NULLS方法。)您是对的。如果stickyUntil通过后发布顺序优先,则它将不起作用。我将更新答案以反映这一点。这些查询是否需要cornjob?我认为在每次选择之前运行更新查询应该更快(至少比完整表扫描更快),因为会有4-5个粘滞点,因此实际更新应该很少。这是真的吗?我想知道(stickyUntil,st)上的索引是否更好??我想这就是我要做的。。。尽管这是个蹩脚的办法。我想使用索引,但似乎不可能随着时间戳的变化…我想这就是我要做的。。。尽管这是个蹩脚的办法。我曾想过使用索引,但随着时间戳的变化似乎不可能。您的第一个查询看起来不错。工会没有错。是否认为在应用限制之前,您拉入了太多行?那么为什么要在联合中的每个子查询中添加一个“limitz”?这会将子查询返回的整个集合限制在最多2z个记录的范围内。。然后为了确定第二次查询时的偏移量,我必须为第一次查询调用一个计数。如果有5个胶粘物,那么偏移量10应该是5。。我应该这样做吗?@Paths