Oracle sql subselect 查找聚合值
Posted
技术标签:
【中文标题】Oracle sql subselect 查找聚合值【英文标题】:Oracle sql subselect to find aggregated values 【发布时间】:2012-11-12 20:15:47 【问题描述】:我有一张包含产品、日期/时间和价格的表格。我将日期/时间拆分到另一列,我刚刚拆分了小时部分。我需要按小时查找价格值的高点/低点/开盘价/收盘价。我可以通过在 max()/min() 的选择部分中进行子选择并按产品和小时加入数据来轻松获得高/低。我现在需要打开/关闭,这将是每小时的第一条记录和每小时的最后一条记录。每小时的每条记录的高/低/开/关都应该相同。
示例结果。请注意所有 7 小时记录的最高价是 55,这就是所有 7 小时记录中的最高价,最低价是 30,因为它是所有 7 小时记录中的最低价,50 是开盘价,因为第一个价格(按日期/时间排序at 7:15) 是 50。收盘价是按日期/时间排序的一小时内的最后一个价格,即 30。
Product, Date, Hour, Price, High, Low, Open, Close
A, 11/12/2012 7:15, 7, 50, 55, 30, 50, 30
A, 11/12/2012 7:28, 7, 55, 55, 30, 50, 30
A, 11/12/2012 7:30, 7, 40, 55, 30, 50, 30
A, 11/12/2012 7:35, 7, 45, 55, 30, 50, 30
A, 11/12/2012 7:55, 7, 30, 55, 30, 50, 30
所以再次回顾一下,高/低很容易,因为我在选择部分中对同一个表进行最大/最小查询的子选择,但不知道如何为打开/关闭做同样的事情以获得第一个和基于日期/时间字段的最后记录。
【问题讨论】:
为定价表设置每小时更新 ;) 无论如何,请发布您目前拥有的任何代码。如果您传入表的记录按时间顺序排列。例如下午 1 点的第一条记录是开放的。然后在 60 分钟后,您可以检查哪条记录(即您的收盘价)。一般来说,每个价格变动都附有一个时间。那是怎么回事? :) 所以这是历史数据,不是实时的,所以我有所有的时间。我通过 sql 询问如何获得给定小时内所有记录的第一个和最后一个。例如我有: select price, (select max(price) from price_tbl j where i.product = j.product and i.hr = j.hr) high from price_tbl i 我对 min 做同样的事情,但是第一个如何和最后一个记录。如果 oracle 有一个 first() 和 last() 这会很容易:) 【参考方案1】:将此添加为子查询以获取 Open,并适当地替换产品密钥和小时:
SELECT * FROM (
Select Open
FROM <table name>
WHERE product = '<product key>'
AND hour='<the hour>'
ORDER BY Date
) WHERE rownum = 1
将此添加为子查询以获取关闭,适当地替换产品密钥和小时:
SELECT * FROM (
Select Close
FROM <table name>
WHERE product = '<product key>'
AND hour='<the hour>'
ORDER BY Date desc
) WHERE rownum = 1
这里的技巧是正确设置结果排序并使用rownum = 1
仅获取第一个结果。
另一种选择:
SELECT Open
FROM <table name>
WHERE product = '<product key>'
AND hour='<the hour>'
AND Date = (
SELECT min(Date)
FROM <table name>
WHERE product = '<product key>'
AND hour='<the hour>'
)
SELECT Close
FROM <table name>
WHERE product = '<product key>'
AND hour='<the hour>'
AND Date = (
SELECT max(Date)
FROM <table name>
WHERE product = '<product key>'
AND hour='<the hour>'
)
这种方法的一个缺点是这些语句不能保证返回单行。这意味着如果对于给定的产品,在同一小时有两个条目,具有相同的日期值,即最小值/最大值,它将返回 2 行,在用作子查询时导致异常。
虽然这可能是一件好事,但与其随意选择一行,您会知道存在特定问题,并且可能会更新查询以做出更明智的决定。
【讨论】:
请参阅我认为 rownum 是在 order by 子句之前计算的,如果它在同一个查询中并且此时不能保证它是任何特定的顺序。所以这意味着我必须对它进行子查询,这不起作用,因为在 select 语句中你不能有 2 个嵌套并使用最外面的表的连接。这就是问题所在。 我很确定订单将首先完成。寻找参考。与此同时,您是否尝试过运行它? 你是对的,它的顺序是在rownum
之后完成的,你必须把它包装起来。 ORACLE SQL ROWNUM execution order。唯一的其他选项我仍然仍然有 2 个订阅,基本上在日期列上使用 min 和 max。如果你愿意,我可以发布它,但我认为它比上面的更糟糕。【参考方案2】:
我会为此使用排名函数:
select product, datestr, hour,
max(case when seqnum_open = 1 then price end) as Open,
max(case when seqnum_close = 1 then price end) as Close,
max(price) as High,
min(price) as Low
from (select t.*,
row_number() over (partition by product, datestr, hour order by date) as seqnum_open,
row_number() over (partition by product, datestr, hour order by date desc) as seqnum_close
from (select t.*,
to_char(date, 'YYYY-MM-DD') as datestr
from t
) t
) t
group by product, datestr, hour
【讨论】:
以上是关于Oracle sql subselect 查找聚合值的主要内容,如果未能解决你的问题,请参考以下文章
查找 SQL 聚合函数调用中的百分比可能没有嵌套聚合或窗口函数