【问题标题】:Select latest values for group of related records为相关记录组选择最新值
【发布时间】:2016-07-15 22:11:32
【问题描述】:

我有一个表格,其中包含可按多个属性进行逻辑分组的数据(例如外键)。数据在连续时间间隔上是连续的;即它是一个时间序列数据。我想要实现的是只为每组组选择最新的值。

这是示例数据:

+-----------------------------------------+
| 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 秒才能完成。我的猜测是由于子选择首先选择了大量记录而发生这种情况。

有什么方法可以加快这个查询速度,还是我在错误的方向上试图按照我的方式进行?

【问题讨论】:

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


    【解决方案1】:

    Postgres 为此提供了方便的distinct on

    select distinct on (relation_id, code) t.*
    from t
    order by relation_id, code, date desc;
    

    【讨论】:

    • 非常感谢!比我想象的要容易;我最初把它复杂化了一点,忽略了最简单的解决方案。
    【解决方案2】:

    因此,您的查询使用的列名与示例数据不同,因此很难判断,但您似乎只想按日期以外的所有内容进行分组?假设您没有多个最近的日期,这样的事情应该可以工作。基本上不使用窗口功能,使用适当的分组依据,您的引擎应该更好地优化查询。

    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
    

    【讨论】:

      【解决方案3】:

      其他选项:

      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
      

      这将为您分区的任何内容以及您订购的任何内容返回最高值。

      【讨论】:

        【解决方案4】:

        我相信我们可以尝试这样的事情

           SELECT CODE,Relation_ID,Date,MAX(value)value FROM mytable
        
            GROUP BY CODE,Relation_ID,Date
        

        【讨论】:

          猜你喜欢
          • 2014-09-10
          • 2019-03-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-15
          • 1970-01-01
          • 1970-01-01
          • 2021-01-01
          相关资源
          最近更新 更多