我有一个表,可以容纳多个属性(例如外键)可逻辑分组的数据。数据在连续时间间隔内是连续的;即它是时间序列数据。我想要实现的是仅为每组组选择最新值。
以下是示例数据:
+-----------------------------------------+
| code | value | date | relation_id |
+-----------------------------------------+
| A | 1 | 01.01.2016 | 1 |
| A | 2 | 02.01.2016 | 1 |
| A | 3 | 03.01.2016 | 1 |
| A | 4 | 01.01.2016 | 2 |
| A | 5 | 02.01.2016 | 2 |
| A | 6 | 03.01.2016 | 2 |
| B | 1 | 01.01.2016 | 1 |
| B | 2 | 02.01.2016 | 1 |
| B | 3 | 03.01.2016 | 1 |
| B | 4 | 01.01.2016 | 2 |
| B | 5 | 02.01.2016 | 2 |
| B | 6 | 03.01.2016 | 2 |
+-----------------------------------------+
以下是所需输出的示例:
+-----------------------------------------+
| code | value | date | relation_id |
+-----------------------------------------+
| A | 3 | 03.01.2016 | 1 |
| A | 6 | 03.01.2016 | 2 |
| B | 3 | 03.01.2016 | 1 |
| B | 6 | 03.01.2016 | 2 |
+-----------------------------------------+
为了正确看待这一点 - 对于每个相关对象,我想选择具有最新日期的每个代码。
这是我带来的选择。我使用了ROW_NUMBER OVER (PARTITION BY...)
方法:
SELECT indicators.code, indicators.dimension, indicators.unit, x.value, x.date, x.ticker, x.name
FROM (
SELECT
ROW_NUMBER() OVER (PARTITION BY indicator_id ORDER BY date DESC) AS r,
t.indicator_id, t.value, t.date, t.company_id, companies.sic_id,
companies.ticker, companies.name
FROM fundamentals t
INNER JOIN companies on companies.id = t.company_id
WHERE companies.sic_id = 89
) x
INNER JOIN indicators on indicators.id = x.indicator_id
WHERE x.r <= (SELECT count(*) FROM companies where sic_id = 89)
它有效,但问题是它很慢;当使用大约5%的生产数据时,相当于大约300万fundamentals
个记录,这个选择大约需要10秒才能完成。我的猜测是由于子选择首先选择大量记录而发生的。
有没有什么方法可以加快这个查询速度,还是我正朝着错误的方向努力尝试按照我的方式去做?
答案 0 :(得分:1)
Postgres为此目的提供方便的distinct on
:
select distinct on (relation_id, code) t.*
from t
order by relation_id, code, date desc;
答案 1 :(得分:0)
因此,您的查询使用的列名不同于您的示例数据,因此很难说,但看起来您只想按日期除外?假设您没有多个最近的日期,这样的事情应该有效。基本上不要使用窗口功能,使用适当的组,你的引擎应该更好地优化查询。
SELECT mytable.code,
mytable.value,
mytable.date,
mytable.relation_id
FROM mytable
JOIN (
SELECT code,
max(date) as date,
relation_id
FROM mytable
GROUP BY code, relation_id
) Q1
ON Q1.code = mytable.code
AND Q1.date = mytable.date
AND Q1.relation_id = mytable.relation_id
答案 2 :(得分:0)
其他选择:
SELECT DISTINCT Code,
Relation_ID,
FIRST_VALUE(Value) OVER (PARTITION BY Code, Relation_ID ORDER BY Date DESC) Value,
FIRST_VALUE(Date) OVER (PARTITION BY Code, Relation_ID ORDER BY Date DESC) Date
FROM mytable
这将返回您分区的最高值,以及您订购的任何内容。
答案 3 :(得分:0)
我相信我们可以尝试这样的事情
SELECT CODE,Relation_ID,Date,MAX(value)value FROM mytable
GROUP BY CODE,Relation_ID,Date