如何计算复杂Group By之后的上一行/天的百分比增长?

时间:2012-12-02 16:30:00

标签: mysql group-by

我有一张表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上看到了类似的问题,但是对于每日价格已经在表格中的情况。我认为这在我的案例中特别复杂,因为每日价格是在几次分组计算后的查询时获得的。

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

2 个答案:

答案 0 :(得分:3)

请查看此参考: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

Resutls:

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请求显示父母**:)

enter image description here

答案 1 :(得分:1)

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