Sql 查询最新和时间间隔数据

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

我的数据集与股票价格非常相似——我每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, 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