【问题标题】:Return rows that are max of one column in Postgresql返回 Postgresql 中最多为一列的行
【发布时间】:2017-06-11 01:12:39
【问题描述】:

我的表test_table中的样本数据:

date           symbol      value      created_time
2010-01-09     symbol1     101        3847474847
2010-01-10     symbol1     102        3847474847
2010-01-10     symbol1     102.5      3847475500
2010-01-10     symbol2     204        3847474847
2010-01-11     symbol1     109        3847474847
2010-01-12     symbol1     105        3847474847
2010-01-12     symbol2     206        3847474847

鉴于上面的表格,我正在尝试找到放置在表格上的最佳索引(日期、符号、值和 created_time 组合应该是唯一的)以及与之一起进行的查询以返回以下内容:

date           symbol      value      created_time
2010-01-09     symbol1     101        3847474847
2010-01-10     symbol1     102.5      3847475500
2010-01-10     symbol2     204        3847474847
2010-01-11     symbol1     109        3847474847
2010-01-12     symbol1     105        3847474847
2010-01-12     symbol2     206        3847474847

我正在为这三者中的每一组查找数据的日期、符号、值列,其中包含最大 created_time 列(在上面的示例中基本上是第 1、3、4、5、6、7 行)。

目前我已经尝试过这个索引...

CREATE UNIQUE INDEX "test_table_date_symbol_value_created_time" 
    ON "test_table" USING btree (date, symbol, value, created_time)

我正在使用这个查询。不知道这是否是最有效的方法,它似乎仍然很慢。

select *
  from(
    select date,
           symbol,
           value,
           created_time,
           max(created_time) over (partition by date, symbol) as max_created_time
     from "test_table"
  ) t
where symbol in ('symbol1', 'symbol2') and created_time = max_created_time

【问题讨论】:

  • 所以您想要每个唯一日期、符号和值组合的 最新 行吗?
  • 是的,很抱歉,我对 SQL 非常缺乏经验,所以一直在尝试阅读大量内容并在询问之前进行有根据的猜测。
  • 对不起,我的意思是说每个日期的最新行,符号组合。

标签: sql postgresql greatest-n-per-group


【解决方案1】:

Postgres 支持window functions 适合这种情况:

select date, symbol, value, created_time
from (select *,
    rank() over (partition by date, symbol order by created_time desc) as rownum
  from test_table) x
where rownum = 1

对于datesymbol 的每个组合,此查询从@987654328 中最高(即最后created_time 的行返回valuecreated_time @ 和symbol

我建议这个索引:

CREATE UNIQUE INDEX test_table_idx 
  ON test_table (date, symbol, created_time, value)

这是一个 覆盖 索引(具有查询所需的所有值,无需访问实际表,并且您已经拥有),但请注意 created_time 来自 之前 value,所以数据已经在它的分区顺序中,而value是最不重要的属性,因为它不参与任何决定返回哪一行。

【讨论】:

  • 你对查询很感兴趣,我怎么能修改它只给出最新的日期,符号唯一的组合(所以只会给出最新的值)。很抱歉,我错误地回答了您的上述评论。
  • @Trevor 我已经从分区中删除了value
  • 感谢您的解释,它们很有意义,至少在我的测试中看起来比我以前的尝试更快。虽然将 created_time 移到 value 之前似乎确实让它变慢了,但我对索引不太了解,所以从长远来看它可能会更快,需要更多的测试(我现在有大约 2400 个符号和大约 1100 万行)。
  • @Travor 尝试执行 analyze test_table 然后重新尝试查询。
【解决方案2】:

Postgresql 有非常方便的distinct on

select distinct on (symbol, date) *
from t
order by symbol, date, created_time desc

https://www.postgresql.org/docs/current/static/sql-select.html#SQL-DISTINCT

【讨论】:

    【解决方案3】:

    替代方案:


    SELECT * FROM test_table tt
    WHERE NOT EXISTS (
        SELECT * FROM test_table nx
        WHERE nx."date" = tt."date"
        AND nx.symbol = tt.symbol
        AND nx.created_time > tt.created_time
        );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      • 2014-11-25
      相关资源
      最近更新 更多