PostgreSQL:按计算值的总和排序

时间:2011-09-30 18:34:34

标签: sql arrays postgresql null

我有一个表tips,其定义如下:

CREATE TABLE tips
(
  tip_id bigserial NOT NULL,
  tip text NOT NULL,
  author text NOT NULL,
  post_date bigint NOT NULL,
  likers character varying(16)[],
  dislikers character varying(16)[],
  likes integer NOT NULL,
  dislikes integer NOT NULL,
  abuse_history character varying(16)[]
);

我需要根据受欢迎程度获得提示,人气的定义是:
 喜欢 - 不喜欢 - (size(abuse_history)* 5)

无论排序顺序如何(ASC / DESC),下面的查询都会给出相同的结果。

select * from tips order by (likes - dislikes - (array_length(abuse_history,1) * 5)) ASC limit 2147483647 offset 0

修改

我插入了3条具有以下值的记录:
1)1喜欢,0不喜欢,0滥用投诉
2)0喜欢,1不喜欢,0滥用投诉
3)0喜欢,0不喜欢,0滥用...

无论排序顺序(ASC / DESC)如何,我都会得到以下顺序: {3,1,2}

有人可以指出我正确的方向吗?

3 个答案:

答案 0 :(得分:2)

考虑一下:

SELECT array_length('{}'::character varying(16)[],1);

空数组的输出为NULL。此外,您的abuse_history本身可以是NULL。所以你需要这样的东西:

SELECT *
  FROM tips
 ORDER BY (likes - dislikes - COALESCE(array_length(abuse_history,1) * 5, 0)) DESC;

反馈后编辑:

适用于 PostgreSQL 9.0 ,如本演示所示:

CREATE TABLE tips
( tip_id bigserial NOT NULL,
  tip text,
  author text,
  post_date bigint,
  likers character varying(16)[],
  dislikers character varying(16)[],
  likes integer,
  dislikes integer,
  abuse_history character varying(16)[]
);


INSERT INTO tips (likes, dislikes, abuse_history)
VALUES(1,0, '{}')
,(1,0, '{}')
,(0,1, '{}')
,(0,0, '{}')
,(1,0, '{stinks!,reeks!,complains_a_lot}');


SELECT tip_id
        , likes
        , dislikes
        , (likes - dislikes - COALESCE(array_upper(abuse_history,1) * 5,0)) as pop
        , (likes - dislikes - array_upper(abuse_history,1) * 5) as fail_pop
  FROM tips
 ORDER BY (likes - dislikes - COALESCE(array_upper(abuse_history,1) * 5,0)) DESC;

输出:

 tip_id | likes | dislikes | pop | fail_pop
--------+-------+----------+-----+----------
      1 |     1 |        0 |   1 |
      2 |     1 |        0 |   1 |
      4 |     0 |        0 |   0 |
      3 |     0 |        1 |  -1 |
      5 |     1 |        0 | -14 |      -14

答案 1 :(得分:2)

为了对此进行调试,请将ORDER BY子句的相同表达式放入SELECT部分。然后检查结果 - 它们真的是你期望的吗?

select *, (likes - dislikes - (array_length(abuse_history,1) * 5)) 
from tips 
order by (likes - dislikes - (array_length(abuse_history,1) * 5)) ASC 
limit 2147483647 offset 0

哦,顺便说一句,剥掉那个愚蠢的LIMITOFFSET的东西。

答案 2 :(得分:0)

试试这个:

select t2.*
from ( select t1.*,
       (likes - dislikes - (array_length(abuse_history,1) * 5)) as popularity
       from tips t1) t2
order by popularity;

编辑:以上通常有效(至少与Oracle有关)。也许使用With子句的以下变体将避免错误。

WITH popularity_query as
     ( select t.*,
              (likes - dislikes - (array_length(abuse_history, 1) * 5)) as popularity
       from tips t)
select * from popularity_query order by popularity