我有一个表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}
有人可以指出我正确的方向吗?
答案 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
哦,顺便说一句,剥掉那个愚蠢的LIMIT
和OFFSET
的东西。
答案 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