我有一个非常大的表,看起来像这样:
event_date (DATE), event_cd (TEXT), bat_id (TEXT)
有几百万行。 type
是存储为字符串的数字,表示一种事件类型(' 14',' 16'等等...)。目标是计算给定日期范围和标识符的值。我创建了一个函数,它接受一个标识符,一个开始日期(作为TEXT)和一个结束日期(作为TEXT)并执行以下操作:
CREATE OR REPLACE FUNCTION wOBA_period(player TEXT, start_date TEXT, end_date TEXT)
RETURNS NUMERIC AS $$
WITH guts AS (SELECT * FROM weights WHERE season = substring(start_date FROM 1 FOR 4) :: INT)
SELECT CASE WHEN sum(CASE WHEN ab_fl = 'T' THEN 1 ELSE 0 END) = 0 THEN NULL ELSE (round(
((SELECT wbb FROM guts) * sum(CASE WHEN event_cd = '14' THEN 1 ELSE 0 END)
+ (SELECT whbp FROM guts) * sum(CASE WHEN event_cd = '16' THEN 1 ELSE 0 END)
+ (SELECT w1b FROM guts) * sum(CASE WHEN event_cd = '20' THEN 1 ELSE 0 END)
+ (SELECT w2b FROM guts) * sum(CASE WHEN event_cd = '21' THEN 1 ELSE 0 END)
+ (SELECT w3b FROM guts) * sum(CASE WHEN event_cd = '22' THEN 1 ELSE 0 END)
+ (SELECT whr FROM guts) * sum(CASE WHEN event_cd = '23' THEN 1 ELSE 0 END)) :: NUMERIC
/ (sum(CASE WHEN ab_fl = 'T' THEN 1 ELSE 0 END) + sum(CASE WHEN event_cd = '14' THEN 1 ELSE 0 END)
+ sum(CASE WHEN sf_fl = 'T' THEN 1 ELSE 0 END) + sum(CASE WHEN event_cd = '16' THEN 1 ELSE 0 END)) :: NUMERIC,
3)) END AS woba
FROM events WHERE bat_id = player AND event_date BETWEEN start_date AND end_date
GROUP BY bat_id;
$$
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
上下文:它根据某些事件计算wOBA(基于加权平均值)。公式如下:
wOBA = (wBB*BB + wHBP*HBP + w1B*1B + w2B*2B + w3B*3B) / (AB+BB+SF+HBP)
并在events
表中,event_cd
对应于公式中的每个组件之一(' 20' = 1B,' 14' = BB等)。最后,权重(公式中的wXX)每年都不同,并存储在我为给定年份提取的表格(weights
)中,暂时以guts
形式提供。
一个问题是这个问题很低。获得wOBA_period
函数调用的结果需要大约8秒。当我尝试更新需要为其5000多行中的每一行进行多个函数调用的不同表时,它会成为一个问题。
是否有任何方法可以改进功能以使其更快一点?
由于
示例数据:
来自events
:
event_date bat_id event_cd
2015-05-30 linda001 2
2015-05-30 hellj001 20
2015-05-30 incie001 20
2015-05-30 polla001 2
2015-05-30 goldp001 9
2015-05-30 goldp001 23
2015-05-30 trumm001 21
2015-05-30 hilla001 2
2015-05-30 pachj001 2
2015-05-30 ramia001 2
所以sum(case when event_cd = '20' then 1 else 0 end) group by bat_id
会返回次数' 20'出现在给定的bat_id
。这是' 1B'的数量。在wOBA公式中。
weights
表每年都有这样的一行:
year wbb whbp w1b w2b w3b whr
2016 0.691 0.721 0.878 1.242 1.569 2.015
这些是公式中每个组成部分的权重。
wOBA_period
函数需要bat_id
和2个日期,并且应该返回一个数字。
答案 0 :(得分:0)
我当然没有您的数据副本,但您可以尝试以下
我的想法是功能没有得到很好的优化,特别是如果它们即时创建查询,但视图可能会有所帮助。