oracle sql查询进一步优化1
Posted
技术标签:
【中文标题】oracle sql查询进一步优化1【英文标题】:oracle sql query optimization further 1 【发布时间】:2016-11-16 09:37:39 【问题描述】:我已经编写了一个查询来从 bdb 中选择 * 以仅获取最新 ACT 中 DAY、INST 组合的 PRICE 中的更新值 我创建了一个像
的表CREATE TABLE bdb(
ACT NUMBER(8) NOT NULL,
INST NUMBER(8) NOT NULL,
DAY DATE NOT NULL,
PRICE VARCHAR2 (3),
CURR NUMBER (8,2),
PRIMARY KEY (ACT,INST,DAY)
);
用它来填充表格
DECLARE
t_day bdb.day%type:= '1-JAN-16';
n pls_integer;
BEGIN
<< act_loop >>
FOR i IN 1..3 LOOP --NUMBER OF ACT i
<< inst_loop >>
FOR j IN 1..1000 LOOP --NUMBER OF INST j
t_day:='3-JAN-16';
<< day_loop >>
FOR k IN 1..260 LOOP --NUMBER OF DAYS k
n:= dbms_random.value(1,3);
INSERT into bdb (ACT,INST,DAY,PRICE,CURR) values (i,j,t_day,n,10.3);
t_day:=t_day+1;
END loop day_loop;
END loop inst_loop;
END loop act_loop;
END;
/
使用此查询 我只得到 DAY,INST,PRICE
select day,inst,price from bdb where (act=(select max(act) from bdb))
minus
select day,inst,price from bdb where act=(select max(act)-1 from bdb);
上面的速度很快。但我想以有效的方式获得所有领域。 我想出来的有点慢,就是这个,
select
e1.*
from
(select
*
from
bdb
where
(act=(select max(act) from bdb))
)e1,
(select day,inst,price from bdb where (act=(select max(act) from bdb))
minus
select day,inst,price from bdb where act=(select max(act)-1 from bdb)) e2
where
e1.day=e2.day and e1.inst=e2.inst;
任何人都可以就如何优化这个提出任何建议吗?或者不使用两个表的交叉连接如何获得所需的输出。帮助我;)
我需要的只是
ACT INST DAY PRI CURR
------------------------------------
3 890 05-MAR-16 3 10.3
3 890 06-MAR-16 2 10.3
3 890 07-MAR-16 2 10.3
3 891 05-MAR-16 2 10.3
3 891 06-MAR-16 1 10.3
3 891 07-MAR-16 2 10.3
4 890 05-MAR-16 3 10.3
4 890 06-MAR-16 2 10.3
4 890 07-MAR-16 1 10.3
4 891 05-MAR-16 2 10.3
4 891 06-MAR-16 2 10.3
4 891 07-MAR-16 1 10.3
这里是 (890,05-MAR-16) (890,06-MAR-16) (890,06-MAR-16) (891,05-MAR-16) (891,06-MAR-16) (891,06-MAR-16) 在行动=3 价格是 3,2,2 2,1,2
but when act=4 happens
(890,07-MAR-16)
(891,06-MAR-16)
(891,07-MAR-16)
price values are change from what they were in act=3.
others not change
最终我需要的是
ACT INST DAY PRI CURR
------------------------------------
4 890 07-MAR-16 1 10.3
4 891 06-MAR-16 2 10.3
4 891 07-MAR-16 1 10.3
【问题讨论】:
【参考方案1】:看起来您在 day、inst 和 price 值之后,其中一行的 act 列具有整个表中的最大 act 值,但没有一行的 act 列少一超过最大行为值。
你可以试试这个:
SELECT day,
inst,
price
FROM (SELECT day,
inst,
price,
act,
MAX(act) OVER () max_overall_act
FROM bdb)
WHERE act IN (max_overall_act, max_overall_act -1)
GROUP BY day, inst, price
HAVING MAX(CASE WHEN act = max_overall_act THEN 1 END) = 1
AND MAX(CASE WHEN act = max_overall_act - 1 THEN 1 END) IS NULL;
首先,子查询在整个表中找到最大的行为值。
然后我们选择所有行为值是最大值或小于该值的行。
之后,我们将行分组并找出哪些行有 act = max act val,但没有 act = max act val -1。
但是,根据您在帖子中所说的:
我已经编写了一个查询来从 bdb 中选择 *,以便仅获取最新 ACT 中 DAY、INST 组合的 PRICE 中的更新值
您提出的查询和我回答中的上述查询似乎都不符合您的要求。
我认为相反,您追求的是:
SELECT act,
inst,
DAY,
price,
curr,
prev_price -- if desired
FROM (SELECT act,
inst,
DAY,
price,
curr,
LEAD(price) OVER (PARTITION BY inst, DAY ORDER BY act DESC) prev_price,
row_number() OVER (PARTITION BY inst, DAY ORDER BY act DESC) rn
FROM bdb)
WHERE rn = 1
AND prev_price != price;
它的作用是使用 LEAD() 分析(基于递减的行为顺序)来查找每一行和每一天的前一行为行的价格,以及行号。
然后要查找最新的行为行,我们只需选择行号为 1 的行以及之前价格与当前价格不匹配的行。然后,您可以根据需要同时显示当前价格和之前的价格。
【讨论】:
感谢您的快速回复...我想我没有正确解释问题....我认为这会清楚地澄清它。更新的问题在上面 你的第一个解释是正确的......但我需要它们的 ACT 和 CURR 字段以有效的方式 道歉;我在第二个查询中错过了AND prev_price != price
条件。现在应该可以了。
感谢:D..它的工作效率很高
另一件小事......检查哪种方法更快的最佳方法是什么,是我们从这种查询中获得的执行时间......SELECT SQL_ID,EXECUTIONS, ELAPSED_TIME,CPU_TIME FROM V$SQL WHERE SQL_ID= (select /* MYCOMMENT1 / sql_id sql_text from v$sql where upper(sql_text) like '%EWTWTWT4%' and sql_text not like '%/ MYCOMMENT1 */ %');以上是关于oracle sql查询进一步优化1的主要内容,如果未能解决你的问题,请参考以下文章