oracle在不同日期获取一列的平均值

时间:2016-07-20 15:41:34

标签: sql oracle mean date-range

有一列名为Price,另一列名为Date_1,其中包含从现在到大约一年后的数据。 我希望在不同日期找到Price的平均值。例如,从现在起2周,从现在起1个月,从现在起6个月......

我可以使用Case When功能吗?

假设:

Location_id |     Date_1  | Price 
------------+-------------+------
   L_1      | 20-JUL-2016 |  105 
   L_1      | 21-JUL-2016 |  117
   ...      |    ...      |  ... 
   L_1      | 16-MAY-2017 |  103 
   L_2      | 20-JUL-2016 |   99 
   L_2      | 21-JUL-2016 |  106 
   ...      |    ...      |  ... 
   L_2      | 16-MAY-2017 |  120 

获得:

Location_id |  Period  | Average_Price 
------------+----------+--------------
   L_1      | 2  weeks |   ... 
   L_1      | 6 months |   ... 
   L_1      | 1 year   |   ... 
   L_2      | 2 weeks  |   ... 
   L_2      | 6 months |   ...
   L_2      | 1 year   |   ... 

在"期间",' 2周'表示从开始日期起2周(sysdate)。和#34; Average_Price"是该时期价格的平均值。

谢谢!这个问题解决了。我还想看另外一个:

还有另一个包含日期信息的表:

Location_id |  Ex_start_date  | Ex_end_date 
------------+-----------------+--------------
   L_1      | 08-JUN-16       |   30-AUG-16
   L_1      | 21-SEP-16       |   25-SEP-16
   L_1      | 08-MAY-17       |   12-MAY-17
   L_2      | 08-AUG-16       |   21-AUG-16
   L_2      | 24-OCT-16       |   29-OCT-16
   L_2      | 15-MAR-17       |   19-MAR-17

超越" Ex_Start_date"和" Ex_End_date"是' Non_Ex'期。在我获得2周和6个月的平均信息后,我想再添加一列,以获得“Non_Ex”的平均价格。和' Ex'条件如上。

希望可以获得如下表格:

Location_id |  Period        | Ex_Condition    |   Average_Price 
------------+----------------+----------------------------------
   L_1      | 2 weeks        |   Ex period     |   ...
   L_1      | 2 weeks        |   Non-Ex period |   ...
   L_1      | 6 months       |   Ex period     |   ...
   L_1      | 6 months       |   Non-Ex period |   ...                                                 
   L_2      | 2 weeks        |   Ex period     |   ...
   L_2      | 2 weeks        |   Non-Ex period |   ...
   L_2      | 6 months       |   Ex period     |   ...
   L_2      | 6 months       |   Non-Ex period |   ...

平均价格将返回' null'如果在EX期间或非期间没有日期。

我怎样才能实现呢?谢谢!

3 个答案:

答案 0 :(得分:0)

你可以这样做:

git submodule foreach --recursive '[[ -f .git ]] && echo "gitdir: $(realpath --relative-to=. $(cut -d" " -f2 .git))" > .git'

localprice 替换为您的表名(您的问题中未提供其名称)。

mydate 替换为日期列的实际名称。我不希望你把它称为 date ,因为这是一个保留字,需要你总是引用它 - 不要那样做:选择另一个名字。

select location_id, period, sum(in_period * price) / nullif(sum(in_period), 0) as avg_price from (select location_id, price, period, case when mydate - days < sysdate then 1 else 0 end in_period from localprice, ( select '2 weeks' as period, 14 as days from dual union select '6 months', 183 from dual ) intervals ) detail group by location_id, period 是Oracle中可用的标准对象,可用于在查询中引入行 - 某些表中没有的行。

或者,您可以创建一个包含您感兴趣的所有期间的表格(2周,4周,......以及它们代表的天数)并使用它而不是双重的联合选择。

这是SQL fiddle。请注意,它在Postgres上运行,因为此时Oracle实例不可用。出于这个原因,我明确地创建了dual并使用了dual而不是current_date。但其余部分则相同。

答案 1 :(得分:0)

未测试,因为OP未提供可用格式的输入数据。

你可能想要一些

的内容
select   location_id, '2 weeks' as period, avg(price) as average_price
from     base_table
where    price is not null
         and
         "date" between SYSDATE and SYSDATE + 13  
                                -- or however you want to define the two week interval
group by location_id
union all
select   location_id, '6 months' as period, avg(price) as average_price
from     base_table
where    price is not null
         and
         "date" between SYSDATE and add_months(SYSDATE, 6) - 1  
                                -- or however you want to define the six month interval
group by location_id
;

请注意date是一个保留的Oracle关键字,不应该用作列名;如果你这样做,你将不得不使用双引号,完全匹配大小写(上下),你可能仍会遇到各种问题。最好只使用非保留字的表和列名称。

答案 2 :(得分:0)

这是@trincot答案的重新措辞版本。它应该比更大的数据集更快。

  • 跳过不需要的行,而不是归零和使用。如果没有符合间隔标准的本地价格,您将不再获得结果行。
  • 与@mathguy答案不同,它仍然只扫描一次本地价格。
  • 如果当地的实际价格具有高度选择性的指数,则可以使用它。
  • 取消注释WHERE子句中的行将有助于提前丢弃行,即在考虑间隔表之前。 ORDERED提示在现实生活中可能是不必要的,但在使用此行时,它会演示正确的解释计划。
  • 在粘合唯一的行时,使用UNION ALL而不是UNION

像往常一样,在你的情况下证明这一点之前,不要相信任何答案。

WITH localprice AS ( SELECT 'L_1' Location_id, TO_DATE('20-JUN-2016') "DATE", 105 Price FROM DUAL UNION ALL SELECT 'L_1' Location_id, TO_DATE('16-MAY-2017') "DATE", 103 Price FROM DUAL UNION ALL SELECT 'L_2' Location_id, TO_DATE('20-JUN-2016') "DATE", 99 Price FROM DUAL UNION ALL SELECT 'L_2' Location_id, TO_DATE('16-MAY-2017') "DATE", 120 Price FROM DUAL ), intervals AS ( SELECT '2 weeks' AS period, 14 AS days FROM dual UNION ALL SELECT '6 months', 183 FROM dual ) SELECT /*+ ORDERED */ location_id, period, AVG(price) AS avg_price FROM localprice CROSS JOIN intervals WHERE "DATE" >= SYSDATE - days -- AND "DATE" >= SYSDATE - (SELECT MAX(days) FROM intervals) GROUP BY location_id, period