【问题标题】:PostgreSQL window function "lag()" only pulls from current resultsetPostgreSQL 窗口函数“lag()”仅从当前结果集中提取
【发布时间】:2015-09-09 00:46:44
【问题描述】:

我正在制作股票行情作为 PostgreSQL 和 AngularJS 的学习经验。

在我的代码查询中,我试图发现前一天的价格变化。我现在在 PHP 中实现数据库查询以便于测试,稍后我将移植到 AngularJS。

数据库设置

prices
--pk
--fund (foreign key to funds.pk)
--price
--price_date

funds
--pk
--fund_name
--summary

查询 通过价格表中的条目获取每个基金的最新价格和之前的价格(以及其他信息)。 这个 $query 是我的 PHP 文件中的一行。

$query = 'SELECT prices.price_date, 
prices.price, 
(lag(prices.price) over (ORDER BY prices.price_date DESC)) as last_price, 
prices.fund, 
funds.fund_name 
FROM prices 
INNER JOIN funds ON prices.fund=funds.pk 
WHERE price_date=(SELECT price_date FROM prices ORDER BY price_date DESC LIMIT 1)';

结果

[
{"price_date":"2015-09-08","price":"17.5901","last_price":null,"fund":"1","fund_name":"L Income"},
{"price_date":"2015-09-08","price":"22.8859","last_price":"17.5901","fund":"2","fund_name":"L 2020"},
{"price_date":"2015-09-08","price":"24.6693","last_price":"22.8859","fund":"3","fund_name":"L 2030"},
{"price_date":"2015-09-08","price":"26.1456","last_price":"24.6693","fund":"4","fund_name":"L 2040"},
{"price_date":"2015-09-08","price":"14.7756","last_price":"26.1456","fund":"5","fund_name":"L 2050"},
{"price_date":"2015-09-08","price":"14.8181","last_price":"14.7756","fund":"6","fund_name":"G Fund"},
{"price_date":"2015-09-08","price":"16.93","last_price":"14.8181","fund":"7","fund_name":"F Fund"},
{"price_date":"2015-09-08","price":"26.369","last_price":"16.93","fund":"8","fund_name":"C Fund"},
{"price_date":"2015-09-08","price":"35.9595","last_price":"26.369","fund":"9","fund_name":"S Fund"},
{"price_date":"2015-09-08","price":"24.0362","last_price":"35.9595","fund":"10","fund_name":"I Fund"}
]

如您所见,lag() 窗口函数仅在当前结果集上绘制,用于拉取上一条记录的 price.price 字段。

我现在很茫然。有人指导吗?

【问题讨论】:

  • 我认为你应该添加partition by子句来获取同一基金前一天的价格,而不是任意基金,像这样:(partition by prices.fund ORDER BY prices.price_date DESC)
  • lag 应该是这样工作的。您可以通过使用更广泛的过滤器并使用lag 并使用它作为子查询,进一步过滤它来获得您想要的行为

标签: sql postgresql


【解决方案1】:

我猜你想要fund 前一天的价格。这需要一个partition by 子句:

SELECT p.price_date, p.price, 
       lag(p.price) over (PARTITION BY p.fund ORDER BY p.price_date DESC) as last_price, 
       p.fund, p.fund_name 
FROM prices p INNER JOIN
     funds f
     ON p.fund = f.pk ;

如果您只希望在最后一个日期使用此信息,请使用子查询:

SELECT pf.*
FROM (SELECT p.price_date, p.price, 
             lag(p.price) over (PARTITION BY p.fund ORDER BY p.price_date DESC) as last_price, 
             p.fund, p.fund_name 
      FROM prices p INNER JOIN
           funds f
           ON p.fund = f.pk
     ) pf
WHERE price_date = (SELECT price_date FROM prices ORDER BY price_date DESC LIMIT 1);

WHERE 子句在分析函数之前进行评估,因此过滤会影响LAG() 选择的记录(如果有)。注意:这假设所有资金的最大 price_date 相同,但这是问题中的逻辑。

【讨论】:

  • 非常感谢!!在你告诉我答案之后,我去查看文档并找到了关于 PARTITION BY 的更详细的讨论。在第一个薪水示例中:postgresql.org/docs/current/static/tutorial-window.html
  • 注意:最终的 SQL 查询使用lead() 或在子查询中按p.price_date ASC 排序——我不完全明白为什么。如果我在子查询中使用lag()DESClast_price 就是null
【解决方案2】:

如果您需要将其与前一天的价格进行比较,您应该使用条件,以便它始终获取前一天的值。

SELECT prices.price_date, 
prices.price, 
case when price_date = (select max(prices_date) from prices) then 
lag(prices.price) over (ORDER BY prices.price_date) 
end as last_price, 
prices.fund, 
funds.fund_name 
FROM prices 
INNER JOIN funds ON prices.fund = funds.pk 
WHERE price_date=(SELECT price_date FROM prices ORDER BY price_date DESC LIMIT 1)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 1970-01-01
    • 1970-01-01
    • 2019-01-04
    • 2021-10-13
    • 2018-12-15
    • 1970-01-01
    相关资源
    最近更新 更多