Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 查询优化以减少多个联接语句_Sql_Oracle_Optimization_Query Optimization - Fatal编程技术网

Sql 查询优化以减少多个联接语句

Sql 查询优化以减少多个联接语句,sql,oracle,optimization,query-optimization,Sql,Oracle,Optimization,Query Optimization,这是表格: CREATE TABLE ABC ( key NUMBER(5), orders NUMBER(5), cost NUMBER(5), dat DATE ); insert into ABC (key, orders, cost, dat) values (1, 3, 5, to_date('10-11- 2017', 'mm-dd-yyyy')); insert into ABC (key, orders, cost,dat) va

这是表格:

CREATE TABLE ABC
(
     key NUMBER(5), 
     orders NUMBER(5), 
     cost NUMBER(5), 
     dat DATE
);

insert into ABC (key, orders, cost, dat) values (1, 3, 5, to_date('10-11- 
2017', 'mm-dd-yyyy'));
insert into ABC (key, orders, cost,dat) values (1, 5, 2, to_date('02-10- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (1, 6, 1, to_date('03-10- 
2017', 'mm-dd-yyyy'));
insert into ABC (key, orders, cost,dat) values (1, 7, 2, to_date('05-10- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (1, 8, 3, to_date('07-10- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (1, 3, 4, to_date('08-10- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (2, 3, 6, to_date('02-10- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (2, 3, 9, to_date('01-10- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (2, 2 ,5, to_date('03-10- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (2, 3, 2, to_date('05-10- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (2, 1, 1, to_date('06-10- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (3, 4, 12, to_date('10-10- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (3, 3, 9, to_date('01-10- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (3, 2 ,5, to_date('05-10- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (3, 3, 2, to_date('06-10- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (3, 1, 1, to_date('07-10- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (3, 4, 12, to_date('11-10- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost, dat) values (1, 3, 5, to_date('10-01- 
2017', 'mm-dd-yyyy'));
insert into ABC (key, orders, cost,dat) values (1, 5, 2, to_date('02-17- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (1, 6, 1, to_date('03-18- 
2017', 'mm-dd-yyyy'));
insert into ABC (key, orders, cost,dat) values (1, 7, 2, to_date('05-14- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (1, 8, 3, to_date('07-13- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (1, 3, 4, to_date('08-12- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (2, 3, 6, to_date('02-11- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (2, 3, 9, to_date('01-15- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (2, 2 ,5, to_date('03-14- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (2, 3, 2, to_date('05-18- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (2, 1, 1, to_date('06-19- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (3, 4, 12, to_date('10-11- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (3, 3, 9, to_date('01-12- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (3, 2 ,5, to_date('05-16- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (3, 3, 2, to_date('06-17- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (3, 1, 1, to_date('07-12- 
2017', 'mm-dd-yyyy')); 
insert into ABC (key, orders, cost,dat) values (3, 4, 12, to_date('12-21- 
2017', 'mm-dd-yyyy')); 
不知道为什么我的结果会重复

我的问题是:

with qone as
(select a.key, a.max_price, max(t.dat) as qo_dat from  ABC t
JOIN
(select key, max(cost) as max_price from ABC
where dat >= to_date('01-01-2017', 'mm-dd-yyyy') and dat < to_date('04-01- 
2017', 'mm-dd-yyyy')
group by key) a on a.key = t.key and a.max_price = t.cost
group by a.key, a.max_price),
qtwo as
(select a.key, a.max_price, max(t.dat) as qt_dat from  ABC t
JOIN
(select key, max(cost) as max_price from ABC
where dat >= to_date('04-01-2017', 'mm-dd-yyyy') and dat < to_date('07-01- 
2017', 'mm-dd-yyyy')
group by key) a on a.key = t.key and a.max_price = t.cost
group by a.key, a.max_price),
qthree as
(select a.key, a.max_price, max(t.dat) as qth_dat from  ABC t
JOIN
(select key, max(cost) as max_price from ABC
where dat >= to_date('07-01-2017', 'mm-dd-yyyy') and dat < to_date('10-01- 
2017', 'mm-dd-yyyy')
group by key) a on a.key = t.key and a.max_price = t.cost
group by a.key, a.max_price),
qfour as
(select a.key, a.max_price, max(t.dat) as qf_dat from  ABC t
JOIN
(select key, max(cost) as max_price from ABC
where dat >= to_date('10-01-2017', 'mm-dd-yyyy') and dat < to_date('01-01- 
2018', 'mm-dd-yyyy')
group by key) a on a.key = t.key and a.max_price = t.cost
group by a.key, a.max_price)
select qo.key, qo.max_price as max_q1, qo.qo_dat, qt.max_price as max_q2, 
qt.qt_dat, qth.max_price as max_q3, qth.qth_dat, qf.max_price as max_q4, 
qf.qf_dat from qone qo
join qtwo qt on qt.key = qo.key 
join qthree qth on qth.key = qth.key
join qfour qf on qf.key = qf.key
order by keyenter code here
我想知道是否有办法减少排队

我是怎么做到的?我找到每个季度的最大价格和最大日期,我使用where语句定义季度

我使用分而治之的方法,找到所有四个季度的最高价格和各自的日期,并在钥匙上加入它们。下面一个自定义季度的示例

`select a.key, a.max_price, max(t.dat) as qo_dat from  ABC t
JOIN
(select key, max(cost) as max_price from ABC
where dat >= to_date('01-01-2017', 'mm-dd-yyyy') and dat < to_date('04-01- 
2017', 'mm-dd-yyyy')
group by key) a on a.key = t.key and a.max_price = t.cost
group by a.key, a.max_price`
输出:

可能的优化解决方案:但我正在想办法在它旁边添加一个相应的日期

select 
    t.key, 
    max( case when t.dat >= Tmp.Q1From and t.dat < Tmp.Q1End then t.cost 
else 0 end ) as Q1Tot, 
    max( case when t.dat >= Tmp.Q1End and t.dat < Tmp.Q2End then t.cost else 
0 end ) as Q2Tot, 
    max( case when t.dat >= Tmp.Q2End and t.dat < Tmp.Q3End then t.cost else 
0 end ) as Q3Tot, 
    max( case when t.dat >= Tmp.Q3End and t.dat < Tmp.Q4End then t.cost else 
0 end ) as Q4Tot 
from 
    ABC t,
       ( select 
               to_date('01-01-2017', 'mm-dd-yyyy') Q1From,
               to_date('04-01-2017', 'mm-dd-yyyy') Q1End,
               to_date('07-01-2017', 'mm-dd-yyyy') Q2End,
               to_date('10-01-2017', 'mm-dd-yyyy') Q3End,
               to_date('01-01-2018', 'mm-dd-yyyy') Q4End
            from 
               dual ) Tmp
 where 
        t.dat >= to_date('01-01-2017', 'mm-dd-yyyy')
    and t.dat < to_date('01-01-2018', 'mm-dd-yyyy')
 group by 
    t.key

也许你可以用更短的方式重写它,如:


输出有点不同,但它显示了您想要的内容。不是吗?

而不是使用连接或交叉连接,考虑使用解析函数nthyValueVE来显示4个季度并列的所需值。

n_值返回窗口中第n行的度量值 由解析_子句定义

第一步:找到所有钥匙和季度的最大成本及其相应日期

select *
from (
  select key, dat, to_char( dat, 'Q' ) quarter 
  , max( cost ) over ( partition by key, to_char( dat, 'Q' ) order by cost desc ) maxcost_
  , max( dat ) over ( partition by key, to_char( dat, 'Q' ) order by cost desc ) maxdat_
  , row_number()  over ( partition by key, to_char( dat, 'Q' ) order by cost desc ) rownum_
    from abc
)
where rownum_ = 1 

-- result
KEY  DAT        QUARTER  MAXCOST_  MAXDAT_    ROWNUM_  
1    17-FEB-17  1        2         17-FEB-17  1        
1    14-MAY-17  2        2         14-MAY-17  1        
1    12-AUG-17  3        4         12-AUG-17  1        
1    01-OCT-17  4        5         11-OCT-17  1        
2    10-JAN-17  1        9         15-JAN-17  1        
2    10-MAY-17  2        2         18-MAY-17  1        
3    10-JAN-17  1        9         12-JAN-17  1        
3    10-MAY-17  2        5         16-MAY-17  1        
3    10-JUL-17  3        1         12-JUL-17  1        
3    10-NOV-17  4        12        21-DEC-17  1        

10 rows selected. 
最终查询:将第一个查询用作内联视图,并调用n_值来检索每个季度的值

select unique key
,  nth_value( maxcost_, 1 ) from first over ( partition by key ) q1max
,  nth_value( maxdat_, 1 ) from first over ( partition by key ) q1date
,  nth_value( maxcost_, 2 ) from first over ( partition by key ) q2max
,  nth_value( maxdat_, 2 ) from first over ( partition by key ) q2date
,  nth_value( maxcost_, 3 ) from first over ( partition by key ) q3max
,  nth_value( maxdat_, 3 ) from first over ( partition by key ) q3date
,  nth_value( maxcost_, 4 ) from first over ( partition by key ) q4max
,  nth_value( maxdat_, 4 ) from first over ( partition by key ) q4date
from (
  select *
  from ( 
    select key, dat, to_char( dat, 'Q' ) quarter 
    , max( cost ) over ( partition by key, to_char( dat, 'Q' ) order by cost desc ) maxcost_
    , max( dat ) over ( partition by key, to_char( dat, 'Q' ) order by cost desc ) maxdat_
    , row_number()  over ( partition by key, to_char( dat, 'Q' ) order by cost desc ) rownum_
    from abc
  )
  where rownum_ = 1  
) -- inline view (no name required)
order by key
;

-- result
KEY  Q1MAX  Q1DATE     Q2MAX  Q2DATE     Q3MAX  Q3DATE     Q4MAX  Q4DATE     
1    2      17-FEB-17  2      14-MAY-17  4      12-AUG-17  5      11-OCT-17  
2    9      15-JAN-17  2      18-MAY-17  NULL   NULL       NULL   NULL       
3    9      12-JAN-17  5      16-MAY-17  1      12-JUL-17  12     21-DEC-17 

这是我的代码,但上面两个查询执行得更快

SQL FIDLE在这里:伙计,我不想告诉你,不过没人会读上面的查询。很疯狂。有4个查询相互连接,唯一的区别是where子句选择了不同的日期。我想知道是否可以减少行数和性能。我会使用一个CTE分组,也可以使用四分之一的函数对CHARdate字段“Q”进行分组。请注意。查询返回价格达到峰值的最后日期。如果有多个日期,则只显示最后一个日期。只是说。回答得很好,但我需要问题中显示的日期和格式,因为我将向这个结果集中添加其他列。“结束”函数在做什么?分区类似于group by right?根据文档,例如,OVER是分析函数中使用的分析子句。分区方式创建了一个所谓的滑动窗口。分组方式的一个区别是:每个分组都有多个值-这就是为什么我们使用SELECT UNIQUE。。。为了得到最终的结果。当你每月做一次的时候,你是怎么做的?我试着用“MM”来表示,并且使用了n个值max\u cost,1。。。到N_值max_cost,12?我可能会首先使用外部连接分区来加密数据,然后应用N_值。我已经为您编写了一个示例,请参见我的建议:查找所有月/年组合始终使用4位数表示年!,然后通过使用分区。。。右键连接。这将为您提供每个月/年的行。参见最后一个查询@
select unique key
,  nth_value( maxcost_, 1 ) from first over ( partition by key ) q1max
,  nth_value( maxdat_, 1 ) from first over ( partition by key ) q1date
,  nth_value( maxcost_, 2 ) from first over ( partition by key ) q2max
,  nth_value( maxdat_, 2 ) from first over ( partition by key ) q2date
,  nth_value( maxcost_, 3 ) from first over ( partition by key ) q3max
,  nth_value( maxdat_, 3 ) from first over ( partition by key ) q3date
,  nth_value( maxcost_, 4 ) from first over ( partition by key ) q4max
,  nth_value( maxdat_, 4 ) from first over ( partition by key ) q4date
from (
  select *
  from ( 
    select key, dat, to_char( dat, 'Q' ) quarter 
    , max( cost ) over ( partition by key, to_char( dat, 'Q' ) order by cost desc ) maxcost_
    , max( dat ) over ( partition by key, to_char( dat, 'Q' ) order by cost desc ) maxdat_
    , row_number()  over ( partition by key, to_char( dat, 'Q' ) order by cost desc ) rownum_
    from abc
  )
  where rownum_ = 1  
) -- inline view (no name required)
order by key
;

-- result
KEY  Q1MAX  Q1DATE     Q2MAX  Q2DATE     Q3MAX  Q3DATE     Q4MAX  Q4DATE     
1    2      17-FEB-17  2      14-MAY-17  4      12-AUG-17  5      11-OCT-17  
2    9      15-JAN-17  2      18-MAY-17  NULL   NULL       NULL   NULL       
3    9      12-JAN-17  5      16-MAY-17  1      12-JUL-17  12     21-DEC-17 
select a.key, a.q1tot, b.dat, a.q2tot, c.dat, a.q3tot, d.dat, a.q4tot, e.dat from (
select 
    t.key, 
    max( case when t.dat >= Tmp.Q1From and t.dat < Tmp.Q1End then t.cost else 0 end ) as Q1Tot, 
    max( case when t.dat >= Tmp.Q1End and t.dat < Tmp.Q2End then t.cost else 0 end ) as Q2Tot, 
    max( case when t.dat >= Tmp.Q2End and t.dat < Tmp.Q3End then t.cost else 0 end ) as Q3Tot, 
    max( case when t.dat >= Tmp.Q3End and t.dat < Tmp.Q4End then t.cost else 0 end ) as Q4Tot 
from 
    ABC t,
       ( select 
               to_date('01-01-2017', 'mm-dd-yyyy') Q1From,
               to_date('04-01-2017', 'mm-dd-yyyy') Q1End,
               to_date('07-01-2017', 'mm-dd-yyyy') Q2End,
               to_date('10-01-2017', 'mm-dd-yyyy') Q3End,
               to_date('01-01-2018', 'mm-dd-yyyy') Q4End
            from 
               dual ) Tmp
 where 
        t.dat >= to_date('01-01-2017', 'mm-dd-yyyy')
    and t.dat < to_date('01-01-2018', 'mm-dd-yyyy')
 group by 
    t.key) a
    join 
 ( select key, cost, dat from ABC
  where dat < to_date('04-01-2017', 'mm-dd-yyyy')) b
  on a.key = b.key and a.Q1tot = b.cost
  join
  ( select key, cost, dat from ABC
   where dat >= to_date('04-01-2017', 'mm-dd-yyyy') and dat < to_date('07-01-2017', 
'mm-dd-yyyy')) c
 on a.key = c.key and a.Q1tot = c.cost
 join
 ( select key, cost, dat  from ABC
  where dat >= to_date('07-01-2017', 'mm-dd-yyyy') and dat < to_date('10-01-2017', 
'mm-dd-yyyy')) d
 on a.key = d.key and a.Q1tot = d.cost
    join
 ( select key, cost, dat from ABC
  where dat >= to_date('10-01-2017', 'mm-dd-yyyy') and dat < to_date('01-01-2018', 'mm-dd-yyyy')) e
  on a.key = e.key and a.Q1tot = e.cost