【问题标题】:How to calculate percentage increase from previous row/day after complex Group By?复杂分组后如何计算前一行/天的百分比增加?
【发布时间】:2012-11-20 05:01:21
【问题描述】:

我有一个 IntradayPrices1Minute 表,我在其中存储 1 分钟 时间范围内股票的开盘价、最高价、最低价和收盘价:

  CREATE TABLE `IntradayPrices1Minute` (
  `ticker` varchar(10) NOT NULL DEFAULT '',
  `datetime` datetime NOT NULL,
  `volume` mediumint(11) unsigned NOT NULL,
  `open` decimal(8,4) unsigned NOT NULL,
  `high` decimal(8,4) unsigned NOT NULL,
  `low` decimal(8,4) unsigned NOT NULL,
  `close` decimal(8,4) unsigned NOT NULL,
  PRIMARY KEY (`datetime`,`ticker`),
  UNIQUE KEY `indxTickerDatetime` (`ticker`,`datetime`) USING BTREE
)

我已经成功构建了一个查询,可以在其中计算这些股票的每日开盘价、最高价、最低价和收盘价。这是查询:

SELECT 
    ticker,
    DATE(datetime) AS 'Date',
    SUBSTRING_INDEX( GROUP_CONCAT(CAST(open AS CHAR) ORDER BY datetime), ',', 1 ) as 'Daily Open',
    max(GREATEST(open, high, low, close)) AS 'Daily High',
    min(LEAST(open, high, low, close)) AS 'Daily Low',
    SUBSTRING_INDEX( GROUP_CONCAT(CAST(close AS CHAR) ORDER BY datetime DESC), ',', 1 ) as 'Daily Close'

FROM 
    IntradayPrices1Minute

GROUP BY
    ticker, date(datetime)

这是该查询成功返回的部分结果:

ticker  Date        Open    High    Low     Close
----    ----------  ------  ------  ------  ------ 
AAAE    2012-11-26  0.0100  0.0100  0.0100  0.0100
AAAE    2012-11-27  0.0130  0.0140  0.0083  0.0140
AAAE    2012-11-28  0.0140  0.0175  0.0140  0.0165
AAAE    2012-11-29  0.0175  0.0175  0.0137  0.0137
AAMRQ   2012-11-26  0.4411  0.5300  0.4411  0.5290
AAMRQ   2012-11-27  0.5100  0.5110  0.4610  0.4950
AAMRQ   2012-11-28  0.4820  0.4900  0.4300  0.4640
AAMRQ   2012-11-29  0.4505  0.4590  0.4411  0.4590
AAMRQ   2012-11-30  0.4500  0.4570  0.4455  0.4568

现在的问题是:我想在查询中返回第七列,计算每天收盘价与前一天收盘价之间的百分比增加/减少。

我在 StackOverflow 上看到过类似的问题,但针对的是每日价格已经在表格中的情况。我认为这在我的情况下特别复杂,因为每日价格是在经过多次分组计算后在查询时获得的。

对此的任何帮助将不胜感激。 非常感谢。 博加

【问题讨论】:

  • 表中openhighlowclose 列的含义是什么?例如,为什么一天中途的条目会有close 值?当天每个条目的open 值是否相同? highlow 的值会全天变化吗?您为什么不在那个时刻只拥有一个 price 列?或者bidask 列?事实上,volume 持有什么:自上次记录以来的交易量?我怀疑你应该多花点时间思考一下你的架构。
  • 您好 eggyval,感谢您的回答。 IntradayPrices1Minute 存储 1 分钟 时间范围内的价格变化。因此,对于每只股票,我每分钟至少有 1 笔交易。那一分钟开始时股票的价格是open 价格。那一分钟结束时的价格是close 价格。 volume 列是在那一分钟内交易的股票数量,等等...从这 1 分钟的价格变化中,我创建了查询以获取 openlowhighclose 1 天 时间范围。希望您现在能更好地理解我的问题。谢谢。

标签: mysql group-by


【解决方案1】:

请看一下这个参考:SQLFIDDLE

因此,您当前使用 OHLC 的表用于派生 px_change、px_pct :) 结果为rounded 以显示4 个小数点的变化以及百分比。 Null 用于显示价格没有变化/pct,因为 null 更好地表示价格没有变化 比零价格变化;)

查询:

select ticker, date_format(date,'%m-%d-%Y') as date, open, high,low,close,
pxchange,concat(round(pxpct*100,4),'%') pxpct
from (select case when ticker <> @pxticker 
        then @pxclose := null end, p.*, (close-@pxclose) as pxchange,
    (close-@pxclose)/@pxclose as pxpct, (@pxclose := close),
    (@pxticker := ticker) from pricing p
cross join
    (select @pxclose := null, @pxticker := ticker
     from pricing 
     order by ticker, date limit 1)  as a
  order by ticker, date ) as b
order by ticker, date asc

结果:

TICKER  DATE        OPEN    HIGH    LOW     CLOSE   PXCHANGE  PXPCT
AAAE    11-26-2012  0.01    0.01    0.01    0.01    (null)    (null)
AAAE    11-27-2012  0.013   0.014   0.0083  0.014   0.004     40.0000%
AAAE    11-28-2012  0.014   0.0175  0.014   0.0165  0.0025    17.8571%
AAAE    11-29-2012  0.0175  0.0175  0.0137  0.0137  -0.0028   -16.9697%
AAMRQ   11-26-2012  0.4411  0.53    0.4411  0.529   (null)    (null)
AAMRQ   11-27-2012  0.51    0.511   0.461   0.495   -0.034    -6.4272%
AAMRQ   11-28-2012  0.482   0.49    0.43    0.464   -0.031    -6.2626%
AAMRQ   11-29-2012  0.4505  0.459   0.4411  0.459   -0.005    -1.0776%
AAMRQ   11-30-2012  0.45    0.457   0.4455  0.4568  -0.0022   -0.4793%

** 已根据 OP 在评论中的要求更新了图片以显示括号** :)

【讨论】:

  • 感谢bonCodigo 的回答。但是,您的查询旨在直接应用于已保存 OHLC 价格的表,但请记住,我需要根据查询结果计算每日价格变化百分比。原因是我在表中有 1 分钟 OHLC 价格,而我在查询中计算了每日 OHLC 价格。也许我不够清楚地解释我存储在IntradayPrices1Minute 表中的数据类型。请参阅我在 cmets 顶部留给用户 eggyal 的评论。干杯,谢谢你:-)
  • 您也可以投票支持 Olaf,因为他对您的帮助很大:) 追加非常简单,您可以在问题的整个文本下方添加一个标题,然后添加您的最终答案。抱歉,我目前无法为您找到示例。
  • 抱歉回复晚了。我在这里分解了查询以供您理解。这里有两个主要内容,1. 即使日期不连续,此查询也适用于股票代码 2. 当找到新的股票代码时,它将前一天的价格重置为 null 以确保不计算 px_chg。您能否更新您的问题并将我指向您正在谈论的正确) 括号。顺便说一句,API 进展如何? ;) 您正在从 BBG 下载数据?
  • 只要您的输入数据得到相应处理,您所说的就是正确的:) 因为查询无法知道您所在国家/地区/企业的假期日历。因此,当您提供定价数据时,必须相应地遵守。查询所做的是挑选今天/前一天的数据。例如。周五是假期 - 交易所休市。所以没有价格。在这种情况下,您没有周五的行,但最后一个交易日:周四。在这种情况下,查询将在星期四进行。如果您指的是使查询足够聪明以描绘日历假期-->那么这是新的话题。
  • 为了非常确定,您可以使用您想要测试的不同日期的样本数据进行尝试。并查看查询结果是否按预期出现:) 这是确认的唯一方法。特别是当涉及金钱时;)
【解决方案2】:

high 应该已经包含最大值,low 应该已经包含最小值。

首先,我会重写您的选择并将其创建为视图

create view daily_prices as
SELECT 
    ticker,
    DATE(datetime) AS 'Date',
    SUBSTRING_INDEX( GROUP_CONCAT(CAST(open AS CHAR) ORDER BY datetime), ',', 1 ) as 'Daily Open',
    max(high) AS 'Daily High',
    min(low) AS 'Daily Low',
    SUBSTRING_INDEX( GROUP_CONCAT(CAST(close AS CHAR) ORDER BY datetime DESC), ',', 1 ) as 'Daily Close'
FROM 
    IntradayPrices1Minute
GROUP BY
    ticker, date(datetime)

然后你可以做一个自我加入

select d1.*, d1.`daily close` / d2.`daily close` - 1 as `percent change`
from daily_prices d1
join daily_prices d2 on d1.ticker = d2.ticker and d1.`date` = adddate(d2.`date`, 1)

SQL Fiddle

【讨论】:

  • 谢谢奥拉夫。我痴迷于尝试仅在 1 个查询中执行此操作。我不是很有经验,也不熟悉观点。这样做是否有任何存储或速度影响?谢谢!
  • 此外,尝试你的方法后,这是结果的一部分,我得到:“AAAE 2012年11月27日0.0130 0.0140 0.0083 0.0140 0.3999999999999999 AAAE 2012年11月28日0.0140 0.0175 0.0140 0.0165 0.1785714285714286 AAAE 2012- 11-29 0.0175 0.0175 0.0137 0.0137 -0.16969696969696968
  • 对于我的 cmets 中的混乱情况,我深表歉意。我今天刚开始使用 Stackoverflow,所以一切对我来说都是新的。奥拉夫:我正在尝试测试您建议的方法,但是我发现您在组的第一行中有百分比变化(即:2012 年 11 月 27 日为 AAAE 股票的 0.4)。但这是错误的,因为这是我有数据的第一天,所以没有前一天,所以不应该有任何百分比增加/减少:-(
  • @dodecafonico 第一天是2012-11-26,未列出。如果你也想看到这个,你需要做一个左连接。
  • @dodecafonico 我创建了视图以简化选择。当然,使用两个子查询可以获得相同的结果。
猜你喜欢
  • 2021-11-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-30
  • 1970-01-01
  • 1970-01-01
  • 2010-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多