2017-06-12 52 views
0

我有一个产品部分的表格。如何获取最小和最大请求​​的时间?

__________________________________ 
| SECTION| PRICE |  TIME  | 
|--------------------------------| 
| sec1 | 10 | 06-12-17 12:00| 
| sec2 | 20 | 06-12-17 12:01| 
| sec1 | 20 | 06-12-17 12:02| 
| sec1 | 30 | 06-12-17 12:03| 
| sec2 | 30 | 06-12-17 12:04| 
---------------------------------- 

我需要每个部分的最小值,最大值和平均值。我做的。

SELECT MAX(PRICE), MIN(PRICE), AVG(PRICE) FROM table1 GROUP BY SECTION; 

我还需要有最低和最高价格的销售时间。如果最大的销售是在不同的时间,我需要其中任何一个。如何把它放在一张桌子上?

___________________________________________________________ 
| SECTION| MIN | MAX | AVG | TIME OF MAX | TIME OF MIN | 
|----------------------------------------------------------| 
| sec1 | 10 | 30 | 20 | 06-12-17 12:03 |06-12-17 12:00| 
| sec2 | 20 | 30 | 25 | 06-12-17 12:04 |06-12-17 12:01| 
----------------------------------------------------------- 

回答

2

加入:

t=# WITH a as (
SELECT 
     SECTION 
    , MAX(PRICE) over w 
    , MIN(PRICE) over w 
    , AVG(PRICE) over w 
    , TIME t, price 
    , case when MAX(PRICE) over w = price then TIME end maxt 
    , case when MIN(PRICE) over w = price then TIME end mint 
FROM s154 
WINDOW w as (partition by section) 
) 
select DISTINCT 
     SECTION 
    , MAX 
    , MIN 
    , AVG 
    , max(maxt) over (partition by section) 
    , min(mint) over (partition by section) 
from a 
; 
section | max | min |   avg   |   max   |   min 
----------+-----+-----+---------------------+---------------------+--------------------- 
    sec1 | 30 | 10 | 20.0000000000000000 | 2017-06-12 12:03:00 | 2017-06-12 12:00:00 
    sec2 | 30 | 20 | 25.0000000000000000 | 2017-06-12 12:04:00 | 2017-06-12 12:01:00 
(2 rows) 

而且作为Abelisto指出,on larger data setsFilter聚合前的结果可以显着降低成本。所以加入

where maxt is not null or mint is not null 

到最后推荐。

+0

如果在最后一个查询中添加“maxt不为空或mint不为空”,它可能会更快一点(在我的测试中大约有两次)。 – Abelisto

+0

true - 过滤器应该更加丰富 - 谢谢! –

+0

PS:http://dbfiddle.uk/?rdbms=postgres_9.5&fiddle=b5fcf4bf9e7206c78f16a22bb0b1f0ae – Abelisto

0

假设:最小和最大的价格只能在唯一的一次发生。

试试这个(我选择容易写明白的,而不是有效的查询):使用窗口功能,而不特里普尔

SELECT  sq.* 
      , tmin.time AS minTime 
      , tmax.time AS maxTime 
FROM  (
      SELECT  section 
         , MAX(price) AS maxPrice 
         , MIN(price) AS minPrice 
         , AVG(price) AS avgPrice 
      FROM  table1 
      GROUP BY section 
     ) AS sq 
    INNER JOIN table1 AS tmin 
     ON tmin.section = sq.section 
     AND tmin.price = sq.minPrice 
    INNER JOIN table1 AS tmax 
     ON tmax.section = sq.section 
     AND tmax.price = sq.minPrice; 
1

您正在寻找的东西,如Oracle KEEP FIRST,只能在与PostgreSQL的窗口功能进行仿真:

select 
    section, 
    min(price), 
    max(price), 
    avg(price), 
    max(case when rnk_max = 1 then time end) as time_of_max, 
    max(case when rnk_min = 1 then time end) as time_of_min 
from 
(
    select 
    section, 
    price, 
    time, 
    rank() over (partition by section order by price desc) as rnk_max, 
    rank() over (partition by section order by price) as rnk_min 
    from sections 
) ranked 
group by section; 

我使用RANK,这样你就可以得到一个最低或最高价格几条记录。随着max(case ...)我会从集的最新日期。