Sql 查询最新和时间间隔数据
我的数据集与股票价格非常相似——我每5分钟得到一个平均价格、符号、公司名称 我需要做的是能够高效地:Sql 查询最新和时间间隔数据,sql,postgresql,ecto,Sql,Postgresql,Ecto,我的数据集与股票价格非常相似——我每5分钟得到一个平均价格、符号、公司名称 我需要做的是能够高效地: 获取所有符号的最新价格 获取符号的时间间隔价格(即日期N每1小时一次) 目前,我所掌握的情况如下: Stock Table ID | name | symbol Unique between name and symbol (name/symbol can be unique on their own) Indexed on name, symbol (irrelevant here, bu
- 获取所有符号的最新价格
- 获取符号的时间间隔价格(即日期N每1小时一次)
Stock Table
ID | name | symbol
Unique between name and symbol (name/symbol can be unique on their own)
Indexed on name, symbol (irrelevant here, but indexed for text search)
Stock Ticks Table
ID | stock_id | price | updated_at
All columns non null
对于问题1(获取给定符号的最新价格),我已经有点麻烦了-这与其他问题基本相似:
获取每篇文章的最新评论,或者基本上是一个最大的每组n个查询。问题是我的数据会变得非常大(每5分钟一次),所以我认为这是一个很好的预优化案例。我是否应该添加当前价格
列(或当前价格
表)?或者一个分组是否由
/区分?如何高效地编写该查询
对于问题2(获取时间区间价格),我真的有点担心如何为此编写查询。请注意,棘手的部分是数据中可能存在漏洞,例如,如果查询为:
从6月1日到6月10日,每天享受每一个价格
如果没有6月3日的数据,那么它应该试着从中找出最近的时间(过去或现在)
我在Phoenix/Ecto上写这篇文章,所以如果你能用ORM写它,那将是一个加号,但不是必需的。假设PostgreSQL v9.6(你没有指定)
库存表定义
CREATE TABLE stock ( id serial NOT NULL PRIMARY KEY,
name text NOT NULL UNIQUE,
symbol text NOT NULL UNIQUE );
以及价格表的定义
CREATE TABLE pricing ( id int NOT NULL REFERENCES stock (id),
updated_at TIMESTAMP(0) NOT NULL,
price NUMERIC( 10, 2 ) NOT NULL,
PRIMARY KEY (id, updated_at) );
并在没有股票ID的情况下按日期加快价格查找
CREATE INDEX ON pricing (updated_at);
示例stock
值为(1,'Queen','BEE'),(2,'Team Fox','Fox')。
示例定价
值为
(1, '2017-06-17 13:24:59', 12.34),
(1, '2017-06-01 18:00:00', 6.10),
(1, '2017-06-02 17:00:00', 6.20),
(1, '2017-06-03 17:00:00', 6.30),
(2, '2017-06-02 15:00:00', 100.00),
(2, '2017-06-03 15:30:00', 777.00);
获取所有符号的最新价格
SELECT s.*,
(SELECT price
FROM pricing
WHERE id = s.id
ORDER BY updated_at DESC
LIMIT 1) "latest_price"
FROM stock s
WHERE EXISTS (SELECT id FROM pricing p WHERE p.id = s.id);
这将使用存在的条件排除最新价格的NULL
值。如果股票的价格还不知道,那么就把它排除在外,得到空值
替代
获取最新价格
是
以及
从6月1日到6月10日,每天获取每一个价格
首先使用生成适当的日期
WITH RECURSIVE dates (d) AS (
SELECT '2017-06-01 20:00'::timestamp
UNION ALL
SELECT d + interval '24 hours'
FROM dates
WHERE d < '2017-06-04 20:00'::timestamp
)
SELECT d FROM dates ;
您可以调整以下参数
- 开始日期(
'2017-06-01 20:00'::时间戳
)
- 结束日期(
'2017-06-04 20:00'::时间戳
)
- 时间步长(
间隔“24小时”
)
使用日期
WITH RECURSIVE dates (d) AS (
SELECT '2017-06-01 20:00'::timestamp
UNION ALL
SELECT d + interval '24 hours'
FROM dates
WHERE d < '2017-06-04 20:00'::timestamp
)
SELECT symbol, CAST( d AS date ) "day", price, updated_at
FROM stock s
CROSS JOIN dates
JOIN LATERAL (
SELECT updated_at, price
FROM pricing p
WHERE p.id = s.id AND p.updated_at <= d
ORDER BY p.updated_at DESC
LIMIT 1
) latest_prices ON true
ORDER BY 1, 2, 4, 3 ;
-- orders same id = name blocks;
-- use 2, 1, 4, 3 to get same date blocks
symbol
在库存表中是唯一的吗?@pozs是的,symbol和namebehen之间有一个复合唯一索引?所以就其本身而言,symbol
不是唯一的请同时添加索引和约束定义。@pozs添加了约束@你是否看到、检查、投票并接受答案(如果正确)?
d
---------------------
2017-06-01 20:00:00
2017-06-02 20:00:00
2017-06-03 20:00:00
2017-06-04 20:00:00
WITH RECURSIVE dates (d) AS (
SELECT '2017-06-01 20:00'::timestamp
UNION ALL
SELECT d + interval '24 hours'
FROM dates
WHERE d < '2017-06-04 20:00'::timestamp
)
SELECT symbol, CAST( d AS date ) "day", price, updated_at
FROM stock s
CROSS JOIN dates
JOIN LATERAL (
SELECT updated_at, price
FROM pricing p
WHERE p.id = s.id AND p.updated_at <= d
ORDER BY p.updated_at DESC
LIMIT 1
) latest_prices ON true
ORDER BY 1, 2, 4, 3 ;
-- orders same id = name blocks;
-- use 2, 1, 4, 3 to get same date blocks
symbol | day | price | updated_at
--------+----------------+--------+---------------------
FOX | 2017-06-02 | 100.00 | 2017-06-02 15:00:00
FOX | 2017-06-03 | 777.00 | 2017-06-03 15:30:00
FOX | 2017-06-04 | 777.00 | 2017-06-03 15:30:00 -- price from 3rd
BEE | 2017-06-01 | 6.10 | 2017-06-01 18:00:00
BEE | 2017-06-02 | 6.20 | 2017-06-02 17:00:00
BEE | 2017-06-03 | 6.30 | 2017-06-03 17:00:00
BEE | 2017-06-04 | 6.30 | 2017-06-03 17:00:00 -- price from 3rd