这是该问题的后续内容,其中对我的查询进行了改进,使其使用窗口函数而不是联接内的聚合LATERAL
。虽然查询现在快得多,但我发现结果不正确。
我需要在x年尾随时间框架上执行计算。例如,price_to_maximum_earnings
每行的计算方法是:max(earnings)
十年前移至当前行,然后除以price
结果。为了简单起见,我们将使用1年。
SQL Fiddle对此问题进行了解答。(Postgres 9.6)
作为一个简单的例子,price
和peak_earnings
用于2010-01-01
可像这样分别计算:
SELECT price
FROM security_data
WHERE date = '2010-01-01'
AND security_id = 'SPX';
SELECT max(earnings) AS min_earnings
FROM bloomberg.security_data
WHERE date >= '2000-01-01'
AND date <= '2010-01-01'
AND security_id = 'SPX';
要做到这一点 ,每行 ,我用的是以下情况:
SELECT security_id, date, price
, CASE WHEN date1 >= min_date
THEN price / NULLIF(max(earnings) FILTER (WHERE date >= date1) OVER w, 0) END AS price_to_peak_earnings
FROM
(
SELECT record_id, security_id, price, date, earnings
, (date - interval '1 y')::date AS date1
, min(date) OVER (PARTITION BY security_id) AS min_date
FROM security_data
) d
WINDOW w AS (PARTITION BY security_id);
我认为这里的问题源于的使用FILTER
,因为它似乎并没有按我希望的那样工作。请注意,在链接的SQL
Fiddle中,我显示了的结果FILTER
,对于每一行,peak_earnings
andminimum_earnings
均为整个数据集的最大值和最小值。它们
应该 是earnings
1年前到当前行的最大值/最小值。
这里发生了什么?从这个问题的答案中我知道我不能简单地说FILTER (WHERE date >= date1 AND date <=current_row.date)
,那么我是否缺少解决方案?我无法使用窗口框架,因为在任何给定的时间范围内,行数都是不确定的,所以我不能只说OVER (ROWS BETWEEN 365 PRECEDING AND CURRENT ROW)
。我可以使用框架 和
滤镜吗?那可能会超过一年,然后筛选器可以捕获每个无效的日期。我已经尝试过了,但是没有成功。
我可以使用框架和滤镜吗?
你 可以的 。但是两者都有限制:
FILTER
子句中的表达式只能看到其获取值的相应行。无法引用窗口函数为其计算值的行。因此 , 除非我们进行 巨大而昂贵的 交叉 联接, 否则我看不到根据 该 行制定过滤器的方法-同一行用于许多不同的计算。或者,我们又回到了LATERAL
那个子查询 可 引用父行。这些限制使您的特定查询难以实施。现在应该是 正确的 :
SELECT *
FROM (
SELECT record_id, security_id, date, price
, CASE WHEN do_calc THEN max(earnings) OVER w1 END AS peak_earnings
, CASE WHEN do_calc THEN min(earnings) OVER w1 END AS minimum_earnings
, CASE WHEN do_calc THEN price / NULLIF(max(earnings) OVER w1, 0) END AS price_to_peak_earnings
, CASE WHEN do_calc THEN price / NULLIF(min(earnings) OVER w1, 0) END AS price_to_minimum_earnings
FROM (
SELECT *, (date - 365) >= min_date AND s.record_id IS NOT NULL AS do_calc
FROM (
SELECT security_id, min_date
, generate_series(min_date, max_date, interval '1 day')::date AS date
FROM (
SELECT security_id, min(date) AS min_date, max(date) AS max_date
FROM security_data
GROUP BY 1
) minmax
) d
LEFT JOIN security_data s USING (security_id, date)
) sub1
WINDOW w1 AS (PARTITION BY security_id ORDER BY date ROWS BETWEEN 365 PRECEDING AND 1 PRECEDING)
) sub2
WHERE record_id IS NOT NULL
ORDER BY 1, 2;
SQL提琴。
问题中没有什么可以说每个security_id
人在同一天都有行。计算security_id
子查询中每个的最小/最大日期minmax
将为我们提供最短的时间范围。
计算的时间范围恰好是该行当前日期之前的365天,并且 不 包括当前行(ROWS BETWEEN 365 PRECEDING AND 1 PRECEDING
)。通常, 将 当前行从要与当前行进行比较的聚合中 排除 会更有用。
我将计算条件调整到了相同的时间范围,以避免出现极端情况:(date - 365) >= min_date
在小提琴中,在1月1日的每一行中添加了1行,您可以看到leap年与固定天数365天形成对比的效果。leap年(2001,2005,…)之后,窗框为空。
我正在使用所有子查询,通常比CTE快一点。
可以肯定的是,我们需要ORDER BY
在框架定义中包括。
w1
用作窗口 名称 。您可以添加w2
,等等,每个可以有任意天数。毕竟,如果需要,您可以适应leap年。甚至可能根据当前日期生成整个查询…问题内容: 好的,起初这只是和我的一个朋友开玩笑,但后来变成了有趣的技术问题:) 我有下表: 该表包含我所有东西的记录,并分别具有数量和优先级(我需要多少)。 我有一个指定体积的袋子,例如。我想从表中选择所有可以放入袋子的东西,首先包装最重要的东西。 这似乎是使用窗口函数的情况,所以这是我想出的查询: 但是,问题在于Postgres抱怨: 如果我删除此过滤器,则会正确计算总列,对结果进行正确排序,
我有以下数据: 现在我想以这样一种方式过滤数据,我可以删除第6行和第7行,对于特定的uid,我想在代码中只保留一行值为'c' 所以预期的数据应该是: 我使用的窗口函数如下所示:
问题内容: 我正在试验Firefox的WebDriver,请问是否可以处理“下载”窗口(接受或拒绝传入的下载请求)? 例如,一段简单的代码: 我已经对此进行了一些尝试,但是还没有找到解决方案。我真的很感谢任何提示。 非常感谢,-V 问题答案: 一种解决方案是更改WebDriver的Firefox配置文件,以将某些MIME类型自动下载到给定目录。 我不确定如何(或是否)在Python中公开此信息,但
问题内容: 我需要通过控制器中的代码关闭当前的fxml窗口 我知道stage.close()或stage.hide()在fx中做到这一点 如何在fxml中实现呢?我试过了 但这不起作用! 所有帮助将不胜感激。谢谢! 问题答案: 如果您还没有关闭按钮,请给它一个fx:id: 在您的控制器类中:
问题内容: 在上一个问题中,我需要计算一个变量出现的次数。 提供的代码如下: 但是,现在我需要对该代码进行改进: 假设我有下表: 现在,我需要计算特定时间段内的出现次数。期望的输出如下(为简单起见,假设时间范围为n = 2天) 也就是说,我需要知道在过去的“ n”个月中,代码“ x”在我的表中出现了多少次。 它在SQL Server 2012中运行。 先感谢您。 问题答案: 将选项与CTE,CRO
问题内容: 如您所知,可以如下初始化对象: 是否可以通过函数定义类似这样的对象: 我的目标实际上是从API中获取对象,并通过ng-repeat将它们显示在列表中 问题答案: 该文件说将采用任何表达方式。因此,是的,只要关联的作用域定义了一个称为的函数,您就可以做上面的事情(我也为乐趣进行了验证)。 请注意,该文档说,这实际上仅旨在用于别名: ngInit用于别名化ngRepeat的特殊属性的唯一适