找到给定日期/时间戳的最近记录(之前或之后)

时间:2014-03-20 18:58:08

标签: sql postgresql psql

我想知道如何利用postgresql的时间戳数据类型来计算一些统计数据。例如,假设我想计算每笔交易后的盈利/亏损,所以我有一个三列表tmp:

create table tmp
(date     timestamp,
 customer text,
 price    numeric)

示例视图:

date                 | customer | price 
2014-03-17 18:23:51  | buyer    | 100
2014-03-17 18:14:24  | buyer    | 101   
2014-03-17 18:09:14  | seller   | 102
2014-03-17 18:03:52  | buyer    | 103
2014-03-17 17:57:51  | seller   | 104
2014-03-17 17:52:43  | seller   | 105
2014-03-17 17:52:36  | buyer    | 106
2014-03-17 17:52:35  | seller   | 107
2014-03-17 17:52:35  | buyer    | 108

现在的目标是找到买方支付的价格与卖方支付的价格之间的差价,该价格基于相反类型的最接近交易(买入或卖出)之前或之后有问题的记录。

例如,从顶部查看交易5:

2014-03-17 17:57:51  | seller   | 104 

客户='买方'立即进行的记录是00:06:01之后,客户='买方'之前的记录是00:05:15之前所以我们想要区分价格104 - 106 = 2.我四处搜寻,但未能找到任何提示。感谢。

编辑:在上面的示例中,它使用之前的价格,但我试图找到一个通用的解决方案,它将决定在计算中使用的最接近的价格。

2 个答案:

答案 0 :(得分:1)

SQL Fiddle

select distinct on (t1.date, t1.customer)
    t1.date, t1.customer, t1.price,
    t1.price - t2.price as price_diff,
    abs(extract(epoch from (t1.date - t2.date))) as seconds_diff 
from
    tmp t1
    inner join
    tmp t2 on t1.customer != t2.customer
order by t1.date desc, t1.customer, seconds_diff

答案 1 :(得分:0)

您的示例是前一个价格。您可以使用窗口/分析函数来执行此操作。

这是个主意。加上"买家的数量"在给定的行之前。这会将行划分为通过具有相同总和来标识的组。对卖家也这样做。现在,在每个组中,分散适当的价格值以获得每种可能性的最新价格:

select t.*,
       max(case when customer = 'buyer' then price end) over (partition by buyer_grp) as prev_buyer_price,
       max(case when customer = 'buyer' then price end) over (partition by buyer_grp) as prev_seller_price
from (select tmp.*,
              as buyer_price,
             (case when customer = 'seller' then price end) as seller_price,
             sum(case when customer = 'buyer' then 1 else 0 end) over
                 (order by date) as buyer_grp,
             sum(case when customer = 'seller' then 1 else 0 end) over
                 (order by date) as seller_grp,
      from tmp
     ) t

然后,您的区别只是一个案例陈述:

select (case when customer = 'buyer' then price - prev_seller_price
             when customer = 'seller' then price - prev_buyer_price
        end) as diff

你可以按照尊重顺序为#34; next"价钱。但是,您的示例仅使用之前的价格(这对我来说很有意义),尽管文本提到了两个方向。