有一列名为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期间或非期间没有日期。
我怎样才能实现呢?谢谢!
答案 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答案的重新措辞版本。它应该比更大的数据集更快。
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