如何提高sql查询的性能

Posted

技术标签:

【中文标题】如何提高sql查询的性能【英文标题】:How to Improve Performance of sql query 【发布时间】:2019-04-16 18:06:13 【问题描述】:

桌子

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-01- 
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-11- 
  2017', 'mm-dd-yyyy')); 
 `

现在,查询

with
one as 
(select t.key, sum(t.cost) as tot, sum(t.orders) as qty from table t
where t.date >= to_date('01-01-2017','mm-dd-yyyy') and 
t.date < to_date('04-01-2017','mm-dd-yyyy')
group by t.key),
two as 
(select t.key, sum(t.cost) as tot, sum(t.orders) as qty from table t
where t.date >= to_date('04-01-2017','mm-dd-yyyy') and 
t.date < to_date('07-01-2017','mm-dd-yyyy')
group by t.key),
three as
(select t.key, sum(t.cost) as tot, sum(t.orders) as qty from table t
where t.date >= to_date('07-01-2017','mm-dd-yyyy') and 
t.date < to_date('10-01-2017','mm-dd-yyyy')
group by t.key),
four as
(select t.key, sum(t.cost) as tot, sum(t.orders) as qty from table t
where t.date >= to_date('10-01-2017','mm-dd-yyyy') and 
t.date < to_date('01-01-2018','mm-dd-yyyy')
group by t.key)
select o.key, o.tot, o.qty, s.tot, s.qty, t.tot, t.qty, f.tot,f.qty 
from one o
left join two s on s.key = o.key
left join three t on t.key = o.key
left join four f on f.key = o.key

我想知道我是否可以提高这个 SQL 查询的性能?

如果您注意到代码,您会看到有一个“Where”语句从不同的日期组中获取结果。大部分查询都是重复的,除了 where 子句。

有没有办法优化查询?在性能和行数方面。

预期的输出格式:我可以对格式部分进行编码,但是,就是这样

【问题讨论】:

日期列有索引吗? 我会在表格中添加。 【参考方案1】:

您似乎正在尝试获取季度总数/数量。可以简化为 sum(case/when)。

SQL Fiddle Result

select 
        t.key, 
        sum( case when t.dat >= Tmp.Q1From and t.dat < Tmp.Q1End then t.cost else 0 end ) as Q1Tot, 
        sum( case when t.dat >= Tmp.Q1From and t.dat < Tmp.Q1End then t.orders else 0 end ) as Q1Qty,
        sum( case when t.dat >= Tmp.Q1End and t.dat < Tmp.Q2End then t.cost else 0 end ) as Q2Tot, 
        sum( case when t.dat >= Tmp.Q1End and t.dat < Tmp.Q2End then t.orders else 0 end ) as Q2Qty,
        sum( case when t.dat >= Tmp.Q2End and t.dat < Tmp.Q3End then t.cost else 0 end ) as Q3Tot, 
        sum( case when t.dat >= Tmp.Q2End and t.dat < Tmp.Q3End then t.orders else 0 end ) as Q3Qty,
        sum( case when t.dat >= Tmp.Q3End and t.dat < Tmp.Q4End then t.cost else 0 end ) as Q4Tot, 
        sum( case when t.dat >= Tmp.Q3End and t.dat < Tmp.Q4End then t.orders else 0 end ) as Q4Qty
    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

并且肯定在( date, key ) 上有一个索引…优化 WHERE 子句的日期字段,优化分组依据的 KEY

一体化操作将防止缺少数字,例如第一季度未售出但在第二、第三或第四季度售出的商品,否则将被排除在最终结果之外。

【讨论】:

它给了我一个错误,不是一个有效的月份。不知道为什么 @StackOne,正在努力...不要做Oracle,所以必须调整一些关键字部分...应该很快。 @StackOne -- 完成。在我的帖子中查看更新的 SQLFiddle 谢谢@DRapp,学习了一项新技术。

以上是关于如何提高sql查询的性能的主要内容,如果未能解决你的问题,请参考以下文章

如何提高子查询的性能或 sql 中子查询的替代方案

如何提高sql查询的性能?

如何提高sql查询的性能

如何提高 SQL Azure 查询性能

如何提高sql中的查询性能?

如何提高查询性能?