请参阅下面的查询,其中我通过直接添加而不使用函数来获取声誉值。
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 AND "PostVote"."createdAt" > '2023-12-23'), 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 AND "PostVote"."createdAt" > '2023-12-23'), 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 是一个聚合函数 - 它的参数是单个表达式,针对每个相关行进行计算,并给出所有结果的总和(如果没有结果则为 NULL) - 而
+
是一个普通的二元运算符:它出现在表达式内部,它的操作数是两个子表达式,对于任何给定的行,它给出两个子表达式给出的总和。
此外,它们处理 NULL 的方式有点不同;当任一子表达式给出 NULL 时,
+
给出 NULL,而 SUM 会跳过 NULL(并且仅当接收到 no 非 NULL 值时才返回 NULL)。
我认为讨论相对性能没有意义,因为它们的使用方式非常不同,因此在使用其中一种与另一种时不存在任何不同的查询。