分析函数改写自关联

数据库环境:SQL SERVER 2005

我们会看到这样的需求,查询部门的员工信息和对应的部门人数,要求在同一行上展示。

在没有分析函数之前,遇到需求,只能通过员工表自关联来实现。

我这里就有一个类似的例子

SELECT COUNT(*)
 FROM   dmrpout_03
        LEFT JOIN ctlm1210 ctlm1210_id_cgroup ON dmrpout_03. id_cgroup = ctlm1210_id_cgroup.id_cgroup
        LEFT JOIN ctlm7161 ctlm7161_id_schtype ON dmrpout_03. id_schtype = ctlm7161_id_schtype .id_schtype
        LEFT JOIN ctlm5003 ctlm5003_id_proc ON dmrpout_03. id_proc = ctlm5003_id_proc.id_proc
        LEFT JOIN ctlm1003 ctlm1003_id_dept ON dmrpout_03. id_dept = ctlm1003_id_dept.id_dept
        LEFT JOIN ctlm5111 ctlm5111_id_wkct ON dmrpout_03. id_wkct = ctlm5111_id_wkct.id_wkct
        LEFT JOIN ctlm1007 ctlm1007_id_clerk ON dmrpout_03. id_clerk = ctlm1007_id_clerk.id_clerk
        LEFT JOIN ctlm3006 ctlm3006_id_stockreas ON dmrpout_03.id_stockreas = ctlm3006_id_stockreas.id_stockreas
        LEFT JOIN ctlm3004 ctlm3004_id_keeper ON dmrpout_03. id_keeper = ctlm3004_id_keeper.id_keeper
        LEFT JOIN ctlm3001 ctlm3001_id_wh ON dmrpout_03. id_wh = ctlm3001_id_wh.id_wh
        LEFT JOIN ctlm5112 ctlm5112_id_pline ON dmrpout_03. id_pline = ctlm5112_id_pline.id_pline
        LEFT JOIN ctlm3001 ctlm3001_id_prodwh ON dmrpout_03. id_prodwh = ctlm3001_id_prodwh.id_wh
        LEFT JOIN ctlm1005 ctlm1005_id_recorder ON dmrpout_03.id_recorder = ctlm1005_id_recorder.id_user
        LEFT JOIN ctlm3002 ctlm3002_id_loc ON dmrpout_03. id_loc = ctlm3002_id_loc.id_loc
        LEFT JOIN ctlm3002 ctlm3002_id_prodloc ON dmrpout_03. id_prodloc = ctlm3002_id_prodloc .id_loc
        LEFT JOIN v_ctlm2004 v_ctlm2004_id_uom ON dmrpout_03. id_uom = v_ctlm2004_id_uom.id_uom
        LEFT JOIN v_ctlm2004 v_ctlm2004_id_secuom ON dmrpout_03.id_secuom = v_ctlm2004_id_secuom.id_uom
 WHERE  dmrpout_03.line_no = ( SELECT    MIN( line_no)
                               FROM     dmrpout_03 b
                               WHERE    b .dmrpout_no = dmrpout_03.dmrpout_no
                                        AND b .fiscal_year = ‘2015‘
                                        AND b .fiscal_period = ‘6‘
                                        AND b .id_dept IN (
                                        SELECT  id_dept
                                        FROM    ctlm1003 ctlm1003_id_dept
                                        WHERE   ctlm1003_id_dept.name_dept LIKE ‘%生产%‘ )
                                        AND b .id_wkct IN (
                                        SELECT  id_wkct
                                        FROM    ctlm5111 ctlm5111_id_wkct
                                        WHERE   ctlm5111_id_wkct.name_wkct LIKE ‘%储运%‘ )
                             )
        AND dmrpout_03 .fiscal_year = ‘2015‘
        AND dmrpout_03 .fiscal_period = ‘6‘
        AND ctlm1003_id_dept .name_dept LIKE ‘% 生产%‘
        AND ctlm5111_id_wkct .name_wkct LIKE ‘% 储运%‘

这条SQL要执行4分多钟才出结果。我们可以从2方面进行优化,第一,SQL里有很多LEFT JOIN,

都是dmrpout_03 LEFT JOIN其它表,如果是一对一关系,则LEFT JOIN后面的表可以省略;

第二,将自连接改写成分析函数。

改写后的SQL如下,只耗时12S就出结果了。

SELECT COUNT (*)
 FROM   ( SELECT    dmrpout_03.line_no ,
                    MIN(line_no ) OVER ( PARTITION BY dmrpout_03.dmrpout_no ) AS minline_no
          FROM      dmrpout_03
                    LEFT JOIN ctlm1003 ctlm1003_id_dept ON dmrpout_03.id_dept = ctlm1003_id_dept.id_dept
                    LEFT JOIN ctlm5111 ctlm5111_id_wkct ON dmrpout_03.id_wkct = ctlm5111_id_wkct.id_wkct
                    LEFT JOIN ctlm3002 ctlm3002_id_loc ON dmrpout_03.id_loc = ctlm3002_id_loc.id_loc
                    LEFT JOIN ctlm3002 ctlm3002_id_prodloc ON dmrpout_03.id_prodloc = ctlm3002_id_prodloc.id_loc
                    LEFT JOIN v_ctlm2004 v_ctlm2004_id_uom ON dmrpout_03.id_uom = v_ctlm2004_id_uom.id_uom
                    LEFT JOIN v_ctlm2004 v_ctlm2004_id_secuom ON dmrpout_03.id_secuom = v_ctlm2004_id_secuom.id_uom
          WHERE     dmrpout_03 .fiscal_year = ‘2015‘
                    AND dmrpout_03 .fiscal_period = ‘6‘
                    AND dmrpout_03 .id_dept IN (
                    SELECT  id_dept
                    FROM    ctlm1003 ctlm1003_id_dept
                    WHERE   ctlm1003_id_dept .name_dept LIKE ‘%生产%‘ )
                    AND dmrpout_03 .id_wkct IN (
                    SELECT  id_wkct
                    FROM    ctlm5111 ctlm5111_id_wkct
                    WHERE   ctlm5111_id_wkct .name_wkct LIKE ‘%储运%‘ )
        ) t
 WHERE  t.line_no = minline_no

通过分析函数的改写,可以减少表的扫描。以后如果遇到类似需求,不妨改成这样试试。

(本文完)

时间: 2025-01-04 22:45:55

分析函数改写自关联的相关文章

Oracle Sql优化之Merge 改写优化Update

1.待改写语句如下 update table1 f set f.ljjine1= (select nvl(sum(nvl(b.jine1,0)),0) from table1 b where b.kjqj<=f.kjqj and b.gs=f.gs and b.bm=f.bm and b.yw=f.yw and b.currency=f.currency and substr(b.kjqj,1,4)=substr(f.kjqj,1,4)), f.jine2 = (select nvl(sum(n

【书评:Oracle查询优化改写】第14章 结尾章

[书评:Oracle查询优化改写]第14章 结尾章 一.1  相关参考文章链接 前13章的链接参考相关连接: [书评:Oracle查询优化改写]第一章 http://blog.itpub.net/26736162/viewspace-1652985/ [书评:Oracle查询优化改写]第二章 http://blog.itpub.net/26736162/viewspace-1654252/ [书评:Oracle查询优化改写]第三章 http://blog.itpub.net/26736162/v

MySQL里面的子查询实例

一,子选择基本用法 1,子选择的定义 子迭择允许把一个查询嵌套在另一个查询当中.比如说:一个考试记分项目把考试事件分为考试(T)和测验(Q)两种情形.下面这个查询就能只找出学生们的考试成绩 select * from score where event_id in (select event_id from event where type='T'); 2,子选择的用法(3种) ?        用子选择来生成一个参考值 在 这种情况下,用内层的查询语句来检索出一个数据值,然后把这个数据值用在外

MySQL 性能调优——SQL 查询优化

如何设计最优的数据库表结构,如何建立最好的索引,以及如何扩展数据库的查询,这些对于高性能来说都是必不可少的.但是只有这些还不够,要获得良好的数据库性能,我们还要设计合理的数据库查询,如果查询设计的很糟糕,即使增加再多的只读从库,表结构设计的再合理,索引再合适,只要查询不能使用到这些东西,也无法实现高性能的查询.所以说查询优化,索引优化,库表结构优化需要齐头并进. 在进行库表结构设计时,我们要考虑到以后的查询要如何的使用这些表,同样,编写 SQL 语句的时候也要考虑到如何使用到目前已经存在的索引,

Oracle分析函数

1. ASCII 返回与指定的字符对应的十进制数; SQL> select ascii(A) A,ascii(a) a,ascii(0) zero,ascii( ) space from dual; A A ZERO SPACE --------- --------- --------- --------- 65 97 48 32 2. CHR 给出整数,返回对应的字符; SQL> select chr(54740) zhao,chr(65) chr65 from dual; ZH C --

Oracle分析函数参考手册

Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是对于每个组返回多行, 而聚合函数对于每个组只返回一行. 常用的分析函数如下所列: row_number() over(partition by ... order by ...) rank() over(partition by ... order by ...) dense_rank() over(partition by ... order by ...) count() over(part

MYSQL中delete删除多表数据与删除关联数据

在mysql中删除数据方法有很多种,最常用的是使用delete来删除记录,下面我来介绍delete删除单条记 录与删除多表关联数据的一些简单实例. 1.delete from t1 where 条件 2.delete t1 from t1 where 条件 3.delete t1 from t1,t2 where 条件 4.delete t1,t2 from t1,t2 where 条件 前3者是可行的,第4者不可行. 也就是简单用delete语句无法进行多表删除数据操作,不过可以建立级联删除,

key的hashcode与equals方法改写

get方法过程:首先计算key的hashcode,找到数组中对应位置的某一元素,然后通过key的equeals方法在对应的链表中找到需要的元素.所以,hashcode与equals方法对于找到对应元素是两个关键的方法. HsahMap的key可以是任何类型,例如User对象,为了保证两个具有相同属性的User对象的hashcode相同,我们需要改写hashcode方法,比方说把hashcode的值的计算与User对象的id关联起来,那么只要user对象拥有相同的id,那么他们的hashcode就

Qt中事件处理的方法(三种处理方法,四种覆盖event函数,notify函数,event过滤,事件处理器。然后继续传递给父窗口。可观察QWidget::event的源码,它是虚拟保护函数,可改写)

一.Qt中事件处理的方式 1.事件处理模式一 首先是事件源产生事件,最后是事件处理器对这些事件进行处理.然而也许大家会问, Qt中有这么多类的事件,我们怎么样比较简便的处理每个事件呢?设想,如果是每个事件都对应同一个事件处理器,在该事件处理器中对不同的事件进行分类处理,这样的弊端有两点:第一,导致该事件处理器过于臃肿复杂:第二,这样不便于扩展,当系统新增加事件类型或者是我们需要使用到自定义事件时,就不得不修改Qt的源码来达到目的.所以Qt设计者的做法是针对不同类型的事件提供不同的事件处理器与之对