[英]Oracle sql subselect to find aggregated values
I have a table that has product, date/time, and price. 我有一个包含产品,日期/时间和价格的表。 I split out the date/time to another column where I just split out the hour part of it.
我将日期/时间拆分到另一列,在其中我只拆分了小时部分。 I need to find high/low/open/close of the price value by hour.
我需要按小时查找价格值的高/低/开/关。 I can get the high/low easy enough by doing a subselect in the select portion where I max()/min() and join the data by product & hr.
通过在我的max()/ min()的选择部分进行子选择,然后按乘积和小时将数据连接起来,我可以轻松实现高/低。 I now need the open/close which will be the first record for each hour and the last record for each hour.
我现在需要打开/关闭,这将是每小时的第一条记录,以及每小时的最后一条记录。 high/low/open/close should all be the same for each record by hour.
高/低/打开/关闭应该按小时为每个记录都相同。
Example result. 结果示例。 notice how the high for all hour 7 records is 55 so that's what placed in all the hour 7 records, the low is 30 because it's the lowest of all hour 7 records, 50 is the open because the first price (sorted by date/time at 7:15) is 50. Close is the last price in the hour sorted by date/time which is 30.
请注意,所有小时7记录的最高价是55,所以这是所有小时7记录的最低价,最低是30,因为它是所有小时7记录中的最低价,50是开盘价,因为第一个价格(按日期/时间排序)在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
So again to recap, high/low is easy as I do subselects in the select part that query against the same table doing max/min, but not sure how to do the same thing for open/close to get the first and last records based on date/time field. 因此,再次回顾一下,高/低很容易,因为我在选择部分中对子表进行了子选择,以对同一张表进行最大/最小查询,但不确定如何对打开/关闭进行相同操作以获取第一条记录和最后一条记录在日期/时间字段上。
Add this as a subquery to get the Open, replacing the product key and hour appropriately: 将其添加为子查询以获取Open,并相应地替换产品密钥和小时:
SELECT * FROM (
Select Open
FROM <table name>
WHERE product = '<product key>'
AND hour='<the hour>'
ORDER BY Date
) WHERE rownum = 1
Add this as a subquery to get the Close, replacing the product key and hour appropriately: 将其添加为子查询以获取关闭,并相应地替换产品密钥和小时:
SELECT * FROM (
Select Close
FROM <table name>
WHERE product = '<product key>'
AND hour='<the hour>'
ORDER BY Date desc
) WHERE rownum = 1
The trick here is setting ordering the result correctly and taking only the first result using rownum = 1
. 这里的技巧是设置结果的正确排序,并使用
rownum = 1
仅获取第一个结果。
Another option: 另外一个选项:
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>'
)
A drawback of this route is that these statements are not guaranteed to return a single row. 该路由的缺点是不能保证这些语句返回单行。 Meaning if for a given product there two entries for the same hour, with the same Date value that are the min/max it will return 2 rows causing an exception when used as a sub-query.
这意味着如果给定产品在同一小时内有两个条目,且具有相同的日期值(即最小/最大),则它将返回2行,用作子查询时会导致异常。
Although that may be a good thing, instead of it arbitrarily picking a row, you will know there is a particular problem and can possibly update the query to make a more intelligent decision. 尽管那可能是一件好事,但您会知道存在一个特定的问题,并且可以更新查询以做出更明智的决策,而不是随意选择一行。
I would use ranking functions for this: 我将为此使用排名函数:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.