今天我尝试玩一下货币,并给了 PostgreSQL 一个机会来帮助我。
我在 PostgreSQL 数据库中有一个表,其中包含三个字段:
CREATE TABLE IF NOT EXISTS binance (
date TIMESTAMP,
symbol VARCHAR(20),
price REAL
)
此表更新时间为 10 到 10 秒,大约有 250 行。间隔之间的符号始终相同。例如数据:
+----------------------------+--------+-------+
| date | symbol | price |
+----------------------------+--------+-------+
| 2018-01-18 00:00:00.000000 | x | 12 |
| 2018-01-18 00:00:00.000120 | y | 15 |
| 2018-01-18 00:00:00.000200 | z | 19 |
| 2018-01-18 00:00:10.080000 | x | 14 |
| 2018-01-18 00:00:10.123000 | y | 16 |
| 2018-01-18 00:00:10.130000 | z | 20 |
+----------------------------+--------+-------+
现在,我想做的是获取每个符号在过去 5 分钟内增长了多少(百分比)。
让我们以一个交易品种为例(ETHBTC
)。该交易品种在过去 5 分钟内的数据如下所示:
+----------------------------+--------+----------+
| date | symbol | price |
+----------------------------+--------+----------+
| 2018-01-19 22:59:10.000000 | ETHBTC | 0.09082 |
| 2018-01-19 22:58:59.000000 | ETHBTC | 0.0907 |
| 2018-01-19 22:58:47.000000 | ETHBTC | 0.090693 |
| 2018-01-19 22:58:35.000000 | ETHBTC | 0.090697 |
| 2018-01-19 22:58:24.000000 | ETHBTC | 0.090712 |
| 2018-01-19 22:58:11.000000 | ETHBTC | 0.090682 |
| 2018-01-19 22:57:59.000000 | ETHBTC | 0.090774 |
| 2018-01-19 22:57:48.000000 | ETHBTC | 0.090672 |
| 2018-01-19 22:57:35.000000 | ETHBTC | 0.09075 |
| 2018-01-19 22:57:24.000000 | ETHBTC | 0.090727 |
| 2018-01-19 22:57:12.000000 | ETHBTC | 0.090705 |
| 2018-01-19 22:57:00.000000 | ETHBTC | 0.090707 |
| 2018-01-19 22:56:49.000000 | ETHBTC | 0.090646 |
| 2018-01-19 22:56:37.000000 | ETHBTC | 0.090645 |
| 2018-01-19 22:56:25.000000 | ETHBTC | 0.090636 |
| 2018-01-19 22:56:13.000000 | ETHBTC | 0.090696 |
| 2018-01-19 22:56:00.000000 | ETHBTC | 0.090698 |
| 2018-01-19 22:55:48.000000 | ETHBTC | 0.090693 |
| 2018-01-19 22:55:37.000000 | ETHBTC | 0.090698 |
| 2018-01-19 22:55:25.000000 | ETHBTC | 0.090601 |
| 2018-01-19 22:55:13.000000 | ETHBTC | 0.090644 |
| 2018-01-19 22:55:01.000000 | ETHBTC | 0.0906 |
| 2018-01-19 22:54:49.000000 | ETHBTC | 0.0906 |
| 2018-01-19 22:54:37.000000 | ETHBTC | 0.09062 |
| 2018-01-19 22:54:25.000000 | ETHBTC | 0.090693 |
+----------------------------+--------+----------+
要选择此数据,我使用以下查询:
SELECT *
FROM binance
WHERE date >= NOW() AT TIME ZONE 'EET' - INTERVAL '5 minutes'
AND symbol = 'ETHBTC'
ORDER BY date DESC;
我想做的是找出每个符号:
- 最后一个值与 10 秒前的值之间的百分比
- 最后一个值与 1 分钟前的值之间的百分比
- 最后一个值与 5 分钟前的值之间的百分比
现在,我有点困惑这样的查询应该是什么样子。更多,我不知道这是否重要,但查询是从 Python 中运行的,所以我可能无法利用完整的 PostgreSQL 功能。
最佳答案
演示
Rextester在线演示:http://rextester.com/QNVGU31219
SQL
下面是比较最新价格和1分钟前价格的SQL:
WITH cte AS
(SELECT price,
ABS(EXTRACT(EPOCH FROM (
SELECT date - (SELECT MAX(date) - INTERVAL '1 minute' FROM binance))))
AS secs_from_prev_timestamp
FROM binance
WHERE symbol = 'ETHBTC')
SELECT price /
(SELECT price FROM binance
WHERE symbol = 'ETHBTC' AND date = (SELECT MAX(date) FROM binance))
* 100.0 AS percentage_difference
FROM cte
WHERE secs_from_prev_timestamp = (SELECT MIN(secs_from_prev_timestamp) FROM cte);
可以简单地更改上面的内容,以与不同时间段之前的价格进行比较,例如通过更改为 INTERVAL '5 分钟'
而不是 INTERVAL '1 分钟'
,或者通过更改对 'ETHBTC' 的两个引用来给出不同交易品种的结果
到不同的符号。
说明
棘手的一点是获取之前的价格。这是通过使用公共(public)表表达式 (CTE) 来完成的,该表达式列出了所有价格以及距所需时间戳的秒数。使用绝对值函数 (ABS
),因此无论大于还是小于目标时间戳,都会找到最接近的时间戳。
结果
在上面的示例中,查询给出的结果为 99.848...%
。该值由 0.090682/0.09082 * 100.0
计算得出,其中 0.09082
是最新价格,0.090682
是一分钟前的价格。
上述内容是基于“百分比差异”含义的假设,但也可以计算其他百分比 - 例如0.09082
比 0.090682
高 0.152%
。 (如果我对百分比差异的解释不符合您的要求,请在评论中回复,我会相应更新答案。)
更新 - “全部执行”查询
在阅读了您对 Dan 的回答的评论后,您希望使用单个查询获得所有这些结果,我在下面发布了一个应该可以满足要求的结果。 Rextester 演示在这里:http://rextester.com/QDUN45907
WITH cte2 AS
(WITH cte1 AS
(SELECT symbol,
price,
ABS(EXTRACT(EPOCH FROM (
SELECT date - (SELECT MAX(date) - INTERVAL '10 seconds' FROM binance))))
AS secs_from_latest_minus_10,
ABS(EXTRACT(EPOCH FROM (
SELECT date - (SELECT MAX(date) - INTERVAL '1 minute' FROM binance))))
AS secs_from_latest_minus_60,
ABS(EXTRACT(EPOCH FROM (
SELECT date - (SELECT MAX(date) - INTERVAL '5 minutes' FROM binance))))
AS secs_from_latest_minus_300
FROM binance)
SELECT symbol,
(SELECT price AS latest_price
FROM binance b2
WHERE b2.symbol = b.symbol AND date = (SELECT MAX(date) FROM binance)),
(SELECT price AS price_latest_minus_10
FROM cte1
WHERE cte1.symbol = b.symbol AND secs_from_latest_minus_10 =
(SELECT MIN(secs_from_latest_minus_10) FROM cte1)),
(SELECT price AS price_latest_minus_60
FROM cte1
WHERE cte1.symbol = b.symbol AND secs_from_latest_minus_60 =
(SELECT MIN(secs_from_latest_minus_60) FROM cte1)),
(SELECT price AS price_latest_minus_500
FROM cte1
WHERE cte1.symbol = b.symbol AND secs_from_latest_minus_60 =
(SELECT MIN(secs_from_latest_minus_60) FROM cte1))
FROM binance b
GROUP BY symbol)
SELECT symbol,
price_latest_minus_10 / latest_price * 100.0 AS percentage_diff_10_secs_ago,
price_latest_minus_60 / latest_price * 100.0 AS percentage_diff_1_minute_ago,
price_latest_minus_500 / latest_price * 100.0 AS percentage_diff_5_minutes_ago
FROM cte2;
关于sql - 如何计算最后一个值与X前的值之间的百分比?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48349604/