请参见下面的查询,其中我从没有函数的直接加法中获得了声誉值.

SELECT
    "User"."id",
    "User"."name",
    "User"."title",
    "User"."about",
    "User"."location",
    "User"."isModerator",
    "User"."createdAt",
    (
--      question vote
        COALESCE(SUM("PostVote"."value" * 10) FILTER (WHERE "value" = 1 AND "Post"."questionId" IS NULL), 0)::int 
        +
        COALESCE(SUM("PostVote"."value" * 2) FILTER (WHERE "value" = -1 AND "Post"."questionId" IS NULL), 0)::int 
        +
--      answer vote
        COALESCE(SUM("PostVote"."value" * 10) FILTER (WHERE "value" = 1 AND "Post"."questionId" IS NOT NULL), 0)::int 
        +
        COALESCE(SUM("PostVote"."value" * 2) FILTER (WHERE "value" = -1 AND "Post"."questionId" IS NOT NULL), 0)::int 
        +
--      accepted answer
        (COALESCE(COUNT("answer"."id"), 0)::int * 15)
    ) as reputation
FROM "User"
LEFT JOIN "Post" ON "Post"."authorId" = "User"."id"
LEFT JOIN "PostVote" ON "PostVote"."postId" = "Post"."id"
LEFT JOIN "Post" as answer ON "Post"."acceptedAnswerId" = "answer"."id"
GROUP BY "User"."id"
ORDER BY reputation DESC, id

我这样做是因为SUM不能嵌套,我最初想做这样的事情.

-- ...
    SUM(
--      question vote
        COALESCE(SUM("PostVote"."value" * 10) FILTER (WHERE "value" = 1 AND "Post"."questionId" IS NULL), 0)::int 
        +
        COALESCE(SUM("PostVote"."value" * 2) FILTER (WHERE "value" = -1 AND "Post"."questionId" IS NULL), 0)::int 
        +
--      answer vote
        COALESCE(SUM("PostVote"."value" * 10) FILTER (WHERE "value" = 1 AND "Post"."questionId" IS NOT NULL), 0)::int 
        +
        COALESCE(SUM("PostVote"."value" * 2) FILTER (WHERE "value" = -1 AND "Post"."questionId" IS NOT NULL), 0)::int 
        +
--      accepted answer
        (COALESCE(COUNT("answer"."id"), 0)::int * 15)
    ) as reputation
-- ...

我很好奇是否有任何性能影响或总结可能导致不正确的值?我已经用负值进行了测试,它工作得很好,也许我遗漏了一些东西.

我本可以通过嵌套查询来使用SUM函数,但我认为这太冗长了.

推荐答案

我本可以通过嵌套查询来使用SUM函数...

不,你不可能.您忽略了聚合函数(sum())和普通运算符(+)之间的根本区别.S的回答已经很详细了.

但既然您表达了对性能影响的担忧:您可以优化对count()的使用,其中never返回null.请参见:

假设引用完整性,则不需要实际加入可接受的答案.只需将非空值计数到p."acceptedAnswerId"即可.(我从一开始就不相信你计算的"接受"是正确的,但我坚持你的逻辑.)

实际上,看起来您可以用更快的count()替换sum()的所有实例.因此,您根本不需要COALESCE:

SELECT u.id, u.name, u.title, u.about, u.location, u."isModerator", u."createdAt"
     ,( -- q & a upvote
       count(*) FILTER (WHERE pv."value" =  1)::int * 10
       -- q & a downvote 
     + count(*) FILTER (WHERE pv."value" = -1)::int * -2
       -- accepted answer
     + count(p."acceptedAnswerId")::int * 15  -- cheaper
      ) AS reputation
FROM   "User"          u
LEFT   JOIN "Post"     p  ON p."authorId" = u.id
LEFT   JOIN "PostVote" pv ON pv."postId" = p.id
-- LEFT JOIN "Post"     a  ON a.id = p."acceptedAnswerId"  -- noise?! 
GROUP  BY u.id
ORDER  BY reputation DESC, u.id;

Sql相关问答推荐

在SQL中向每个子字节组添加字节行

一个SQL查询将在需要的地方多次返回同一成员

UPDATE查询中的乐观锁

如何在SQL Server中拆分包含字符和数字的列?

用于过滤嵌套对象或数组中的JSON数据的WHERE条件

PostgreSQL抽奖查询

snowflake/SQL嵌套的JSON对象和数组

SQL仅返回第一个字母在A-Z之间的值

统计PostgreSQL中前10个最大大小表的行数

使用特定的Order By子句随机化SQL输出

Proc SQL Select Distinct SAS

为什么SQL in中的空子查询有时被视为null

用另一个表中的特定名称替换 SQL 查询中的 ID.但我的两个表都有多个列

每个分组最多 Select 最后 2 个值并并排显示它们

将最近的结束日期与开始日期相匹配

如何根据 SQL Server 中 1 条语句中 SELECT 的结果进行 INSERT 或 UPDATE

字符串从更改到表列和查询中的一行的转换错误

为数组中的每个元素从表中收集最大整数

PostgreSQL 如何在一组项目及其数量上找到完全相同的订单?

SQL 中的问题与包含最大日期的记录连接