2013-03-16 103 views
4

我有一个交易数据表,它是对未来的预测。因此,由相同的日期,类型,位置和产品确定的相同预测因此被多次读取,因为预测随着时间的推移变得更准确并且被重新发送。从多列分组的行中选择最大值的行(PSQL)

我想创建一个查询,将相同类型和相同位置,产品和日期的事务分组,然后从这些组中仅选择具有最新更新时间戳的组。

该表具有现在的行数十万和随着时间的推移,数以百万计,所以相当有效的解决方案,将不胜感激:)

实施例的表:

date | location_code | product_code | quantity | type | updated_at 
------------+------------------+---------------+----------+----------+------------ 
2013-02-04 | ABC | 123 | -26.421 | TRANSFER | 2013-01-12 
2013-02-07 | ABC | 123 | -48.1 | SALE | 2013-01-10 
2013-02-06 | BCD | 234 | -58.107 | SALE | 2013-01-11 
2013-02-06 | BCD | 234 |  -60 | SALE | 2013-01-10 
2013-02-04 | ABC | 123 | -6.727 | TRANSFER | 2013-01-10 

期望的结果:

date | location_code | product_code | quantity | type | updated_at 
------------+------------------+---------------+----------+----------+------------ 
2013-02-04 | ABC | 123 | -26.421 | TRANSFER | 2013-01-12 
2013-02-07 | ABC | 123 | -48.1 | SALE | 2013-01-10 
2013-02-06 | BCD | 234 | -58.107 | SALE | 2013-01-11 

我试过例如:

SELECT t.date, t.location_code, t.product_code, t.quantity, t.type, t.updated_at 
FROM transactions t 
INNER JOIN 
(
    SELECT MAX(updated_at) as max_updated_at 
    FROM transactions 
    GROUP BY product_code, location_code, type, date 
) s on t.updated_at=max_updated_at; 

但这似乎需要很长时间,似乎并不奏效。

谢谢你的帮助!

+1

你是在正确的轨道上加入更有效。只需在子查询中添加更多字段并加入其中。 – 2013-03-16 22:33:37

回答

3
select distinct on ("date", location_code, product_code, type) 
    "date", 
    location_code, 
    product_code, 
    quantity, 
    type, 
    updated_at 
from transactions t 
order by t."date", t.location_code, t.product_code, t.type, t.updated_at desc 
+0

尝试了这一个,但得到了以下错误:'错误:SELECT DISTINCT ON表达式必须匹配初始ORDER BY表达式 LINE 1:选择不同的on(date,location_code,product_code,type)' – jesseniem 2013-03-16 22:49:36

+1

@jesuli更正 – 2013-03-16 22:51:17

+0

谢谢!测试这一个,它似乎是目前为止最有效的解决方案:'$ cat time3 Sun Mar 17 01:06:50 EET 2013 Sun Mar 17 01:06:53 EET 2013 | Sun Mar 17 01:06:54 EET 2013 Sun Mar 17 01:06:57 EET 2013 | 太阳3月17日01:06:58 EET 2013 Sun Mar 17 01:07:02 EET 2013' – jesseniem 2013-03-16 23:13:13

1

谢谢Dan Bracuk!

这是正确的查询:

SELECT t.date, t.location_code, t.product_code, t.quantity, t.type, t.updated_at 
FROM transactions t 
INNER JOIN 
(
    SELECT MAX(updated_at) as max_updated_at, product_code prod, location_code loc, type  typ, date dat 
    FROM transactions 
    GROUP BY product_code, location_code, type, date 
    ) s ON t.updated_at=max_updated_at AND t.location_code=loc AND t.product_code=prod AND t.type=typ AND t.date=dat; 
+1

使用窗口函数可能更有效。在这种情况下,Clodoaldo Neto的“独特的”解决方案可能是最有效的解决方案。 – 2013-03-16 22:50:13

2

这可能是比与派生表

select * 
from (
    select date, 
      location_code, 
      product_code, 
      quantity, 
      type, 
      updated_at, 
      max(updated_at) over (partition by product_code, location_code, type, date) as max_updated 
    from transactions 
) t 
where updated_at = max_updated; 
+0

冉快速非常不科学的性能测试,显示可以忽略不计的性能差异。派生表的方法是time2,这个版本time1:'$ cat time1 Sun 3月17日00:57:09 EET 2013 Sun 3月17日00:57:13 EET 2013 | Sun 3月17日00:57:15 EET 2013 Sun 3月17日00:57:20 EET 2013 | 太阳3月17日零时57分23秒EET 2013 太阳3月17日零时57分29秒EET 2013 $猫时间2 太阳3月17日零时55分45秒EET 2013 太阳3月17日0时55分49秒EET 2013 | Sun 3月17日00:56:06 EET 2013 Sun 3月17日00:56:11 EET 2013 | Sun Mar 17 00:56:14 EET 2013 Sun 3月17日00:56:18 EET 2013 ' – jesseniem 2013-03-16 23:04:42