我正在尝试编写一个PostgreSQL查询来计算幻想棒球点,如here所述。我到目前为止所提供的内容在this SQLfiddle中可用,它可以正确计算每个统计数据的点数,除非是关系。被绑定的团队的积分应该像这样计算:
在平局的情况下,所涉及的每支球队都会得到应付总分数的平均值 - 也就是说,在上面的例子中,如果两个队伍在一个类别中并列第一,那么每个队伍将获得9.5分[(10 + 9) )/ 2 = 9.5]。
您可以在我的SQLfiddle的first和second结果集中查看我的方法中的错误。在第一个结果集中,与9个本垒打并列的球队应该得到3.5分(等级4和3 = 7 = 2除以2),而在第二组中,与33打点相关的团队也应该得到3.5分。 (等级为5,4,3和2 = = 14除以4)。
纠正这些错误的最简单方法是什么,并在每个统计数据的排名中平均分配总分数?
答案 0 :(得分:1)
蛮力方法可能是计算未调整的等级,如下所示:
select hr, sum(raw) / count(*)
from (
select hr,
(select count(*) + 1 from stats) - row_number() over (order by hr desc) as raw
from stats
) r
group by hr
order by hr desc
并将其与stats表结合以获得给定分数的分数。
答案 1 :(得分:1)
在我看来,如果示例不完整,那么在提供的字段中有一个候选键会很好。
考虑以下查询的输出:
SELECT
hr,rbi,
rank() OVER h AS hr_rank,
row_number() OVER h AS hr_rn,
count(*) OVER () - rank() OVER h + 1 AS hr_aprx,
rank() OVER r AS rbi_rank,
row_number() OVER r AS rbi_rn,
count(*) OVER () - rank() OVER r + 1 AS rbi_aprx,
count(*) OVER () AS cnt
FROM
stats
WINDOW h AS (ORDER BY hr DESC), r AS (ORDER BY rbi DESC);
此查询提供与前2个查询相同的信息。如果你要查看它的EXPLAIN (analyze, buffers)
输出,你会看到该表只被访问一次。
我在这里将点列命名为%_aprx
,因为这些是近似点,我们必须计算平均值。
%_aprx
列进行数据分组。我将在这里使用CTE,因为我发现命名的子查询看起来更好。考虑此查询(also on sql-fiddle):
WITH ranks AS (
SELECT
hr, rbi,
rank() OVER h AS hr_rank,
row_number() OVER h AS hr_rn,
count(*) OVER () - rank() OVER h + 1 AS hr_aprx,
rank() OVER r AS rbi_rank,
row_number() OVER r AS rbi_rn,
count(*) OVER () - rank() OVER r + 1 AS rbi_aprx,
count(*) OVER () AS cnt
FROM
stats
WINDOW h AS (ORDER BY hr DESC), r AS (ORDER BY rbi DESC)
)
SELECT
hr, rbi,
(avg(hr_rn) OVER h)::float AS hr_pts,
(avg(rbi_rn) OVER r)::float AS rbi_pts,
(avg(hr_rn) OVER h + avg(rbi_rn) OVER r)::float AS ttl_pts
FROM
ranks
WINDOW h AS (PARTITION BY hr_aprx), r AS (PARTITION BY rbi_aprx)
ORDER BY
ttl_pts DESC, hr_pts DESC;
我正在将结果类型的avg()
调用转换为float
以删除一系列零。你可以在这里选择use round()
function。
我还添加了2个排序条件,仅按ttl_pts
排序是不够的。
请注意,外部查询的窗口定义ORDER BY
有意错过。有了它,你将获得一个平均运行效果(你可以改变查询并看到自己)。