1

我有一个事件表:

create table event (id integer primary key, date timestamptz unique);
insert into event (id, date) values
 (22784, '2012-01-01 01:00:00+00'),
 (22785, '2012-01-01 04:00:00+00'),
 (22786, '2012-01-01 07:00:00+00'),
 (22787, '2012-01-01 10:00:00+00'),
 (22788, '2012-01-01 13:00:00+00'),
 (22789, '2012-01-01 16:00:00+00'),
 (22790, '2012-01-01 19:00:00+00'),
 (22791, '2012-01-01 22:00:00+00'),
 (22792, '2012-01-02 01:00:00+00'),
 (22793, '2012-01-02 04:00:00+00'),
 (22794, '2012-01-02 07:00:00+00'),
 (22795, '2012-01-02 10:00:00+00'),
 (22796, '2012-01-02 13:00:00+00'),
 (22797, '2012-01-02 16:00:00+00'),
 (22798, '2012-01-02 19:00:00+00'),
 (22799, '2012-01-02 22:00:00+00'),
 (22800, '2012-01-03 01:00:00+00'),
 (22801, '2012-01-03 04:00:00+00'),
 (22802, '2012-01-03 07:00:00+00'),
 (22803, '2012-01-03 10:00:00+00'),
 (22804, '2012-01-03 13:00:00+00'),
 (22805, '2012-01-03 16:00:00+00'),
 (22806, '2012-01-03 19:00:00+00'),
 (22807, '2012-01-03 22:00:00+00'),
 (22808, '2012-01-04 01:00:00+00'),
 (22809, '2012-01-04 04:00:00+00'),
 (22810, '2012-01-04 07:00:00+00'),
 (22811, '2012-01-04 10:00:00+00'),
 (22812, '2012-01-04 13:00:00+00'),
 (22813, '2012-01-04 16:00:00+00'),
 (22814, '2012-01-04 19:00:00+00'),
 (22815, '2012-01-04 22:00:00+00'),
 (22816, '2012-01-05 01:00:00+00'),
 (22817, '2012-01-05 04:00:00+00'),
 (22818, '2012-01-05 07:00:00+00'),
 (22819, '2012-01-05 10:00:00+00'),
 (22820, '2012-01-05 13:00:00+00'),
 (22821, '2012-01-05 16:00:00+00'),
 (22822, '2012-01-05 19:00:00+00'),
 (22823, '2012-01-05 22:00:00+00'),
 (22824, '2012-01-06 01:00:00+00'),
 (22825, '2012-01-06 04:00:00+00'),
 (22826, '2012-01-06 07:00:00+00'),
 (22827, '2012-01-06 10:00:00+00'),
 (22828, '2012-01-06 13:00:00+00'),
 (22829, '2012-01-06 16:00:00+00'),
 (22830, '2012-01-06 19:00:00+00'),
 (22832, '2012-01-06 22:00:00+00'),
 (22833, '2012-01-07 01:00:00+00'),
 (22834, '2012-01-07 04:00:00+00'),
 (22835, '2012-01-07 07:00:00+00'),
 (22836, '2012-01-07 10:00:00+00'),
 (22837, '2012-01-07 13:00:00+00'),
 (22838, '2012-01-07 16:00:00+00'),
 (22839, '2012-01-07 19:00:00+00'),
 (22840, '2012-01-07 22:00:00+00'),
 (22841, '2012-01-08 01:00:00+00'),
 (22842, '2012-01-08 04:00:00+00'),
 (22843, '2012-01-08 07:00:00+00'),
 (22844, '2012-01-08 10:00:00+00'),
 (22845, '2012-01-08 13:00:00+00'),
 (22846, '2012-01-08 16:00:00+00'),
 (22847, '2012-01-08 19:00:00+00'),
 (22848, '2012-01-08 22:00:00+00'),
 (22849, '2012-01-09 01:00:00+00'),
 (22850, '2012-01-09 04:00:00+00'),
 (22851, '2012-01-09 07:00:00+00'),
 (22852, '2012-01-09 10:00:00+00'),
 (22853, '2012-01-09 13:00:00+00'),
 (22854, '2012-01-09 16:00:00+00'),
 (22855, '2012-01-09 19:00:00+00'),
 (22856, '2012-01-09 22:00:00+00'),
 (22857, '2012-01-10 01:00:00+00'),
 (22858, '2012-01-10 04:00:00+00'),
 (22859, '2012-01-10 07:00:00+00'),
 (22860, '2012-01-10 10:00:00+00'),
 (22861, '2012-01-10 13:00:00+00'),
 (22862, '2012-01-10 16:00:00+00'),
 (22863, '2012-01-10 19:00:00+00'),
 (22864, '2012-01-10 22:00:00+00')
;

我想从每天获取最大时间戳的 id。我所拥有的是:

select date::date as date, id
from event e
where date = (
    select max(date)
    from event
    where date_trunc('day', date) = date_trunc('day', e.date)
)
order by date;
    date    |  id   
------------+-------
 2011-12-31 | 22784
 2012-01-01 | 22792
 2012-01-02 | 22800
 2012-01-03 | 22808
 2012-01-04 | 22816
 2012-01-05 | 22824
 2012-01-06 | 22833
 2012-01-07 | 22841
 2012-01-08 | 22849
 2012-01-09 | 22857
 2012-01-10 | 22864
(11 rows)

它按预期工作,但性能非常糟糕。有什么建议么?

4

3 回答 3

2

DISTINCT ON 可能表现更好:

SELECT DISTINCT ON (d) date_trunc('day',date)::date as d ,id
FROM event 
ORDER BY d desc, date desc;

如果结果必须按日期升序排序,则需要另一个级别的排序:

SELECT d,id 
FROM (
    SELECT DISTINCT ON (d) date_trunc('day',date)::date as d ,id
    FROM event 
    ORDER BY d desc, date desc
) s
ORDER BY d;
于 2012-06-12T20:42:08.777 回答
1
Select date,id from event
inner join (
    Select Max(date_trunc('day', date) as LatestDay 
    From event
) On LatestDay = date_trunc('day', date)

可能会更好一些,但 date_trunc 函数正在杀死你。这可能值得一试。

CREATE INDEX ON event ((date_trunc('day',date)));
于 2012-06-12T17:47:11.813 回答
1

这应该快得多:

SELECT DISTINCT ON (1)
       date::date, id
FROM   event e
ORDER  BY 1, e.date DESC;  -- e.date, not just date!
  • 获得升序不需要另一个级别的排序。

  • date_trunc()没有必要。铸造日期可以完成这项工作。

  • ORDER BY子句中,一定要对表进行限定e.date以选择源列,而不是同名的输出列。由于凌乱的 SQL 标准,可见性规则在这里令人困惑。

  • 顺便说一句,date是每个 SQL 标准中的保留字。您不会将其用作现实世界中的列名,对吗?在这个小例子中已经很混乱了。


另一种方法是使用窗口函数:

SELECT DISTINCT ON (1)
       date::date
      ,first_value(id) OVER (PARTITION BY date::date ORDER BY date DESC) AS id
FROM   event
ORDER  BY 1;

更具可读性,但速度较慢。

于 2012-06-15T03:40:04.467 回答