如何避免SQL中的CTE或子查询?

时间:2015-09-16 09:22:58

标签: django postgresql

问题

假设我们有1作为foo,我们希望foo + 1作为SQL中的bar。

使用CTE或子查询,例如: -

select foo+1 as bar from (select 1 as foo) as abc;

我们会得到(在我正在使用的postgre中): -

 bar 
-----
  2

但是,当我尝试以下操作时: -

select 1 as foo, foo+1 as bar;

发生以下错误: -

ERROR:  column "foo" does not exist
LINE 1: select 1 as foo, foo+1 as bar;
                         ^

如果不使用CTE或子查询,有没有办法解决这个问题?

我为什么要问?

我正在使用Django进行Web服务,对数据库中的对象进行排序和分页,我必须抓住upvotes和downvotes的计数,并对这两个值进行一些额外的数学操作(即计算wilson得分间隔),这两个值被多次使用。

我现在所知道的就是extra()函数,而不会破坏ORM(?)[例如lazy queryset和prefetch_related()函数]。

因此,当我计算分数时,我需要一种方法从某个地方调用这两个值而不是多次执行SELECT。 (或者说现实情况并非如此?)

PS。目前我将投票计数存储为数据库字段并更新它们,但我已经有了一个投票模型,因此更新投票计数并将投票插入数据库似乎多余且缓慢

1 个答案:

答案 0 :(得分:1)

不,您需要子查询或CTE来执行此操作。但有一种选择:创建存储过程。

CREATE FUNCTION wilson(upvote integer, downvote integer) RETURNS float8 AS $$
DECLARE
  score float8;
BEGIN
  -- Calculate the score
  RETURN score;
END; $$ LANGUAGE plpgsql STRICT;

在您的ORM中,您现在将该函数称为SELECT语句的一部分:

SELECT id, upvotes, downvotes, wilson(upvotes, downvotes) FROM mytable;

还可以使代码更清晰。