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 標準のおかげで、ここでは可視性ルールが混乱しています。

  • ところで、すべての SQL 標準date予約語です。現実世界でそれを列名として使用するつもりはありませんよね? 小さな例ではすでに混乱しています。


別の方法は、ウィンドウ関数を使用することです。

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 に答える