选择计数:比较两个查询

时间:2017-12-28 15:31:13

标签: sql oracle

我有两个问题。

第一个是旧的查询非ANSI

SELECT 
    COUNT(ses) 
FROM
    (SELECT
         sa.ses, sa.att, sa.ser, 
         ccp.sta, ccp.end,
         c.id_, c.per, c.is_,
         ccp.clt_
     FROM 
         sa, tn, ccp, cp, c,
         (SELECT DISTINCT sa.ses
          FROM sa, sapa
          WHERE sa.ses = sapa.ses
            AND sapa.pro IN (61,62)
            AND sa.full >= to_date('1/1/2013','mm/dd/yyyy')) sapa1
     WHERE 
         1=1
         AND sa.ses = sapa1.ses (+)
         AND sa.ses = tn.ses
         AND ccp.cli = c.cli
         AND c.cus = sa.pro
         AND substr(c.hea,1,1) = 'H'
         AND sa.ful >= ccp.sta
         AND sa.ful < nvl(ccp.end('9/9/9000','mm/dd/yyyy'))
         AND sa.ful >= to_date('1/1/2013','mm/dd/yyyy')
         AND sa.ful <= sysdate
         AND ccp.cli = cp.cli
         AND cp.clie = 1
         AND sa.proj <> 'MMA'
         AND c.pers IS NOT NULL)

第二次我改写为ANSI

 SELECT COUNT(SES) FROM (
 SELECT
 SA.FUL,
 SA.SES,
 SA.ATT,
 SA.SER,
CCP.STA,
CCP.END,
C.ID_,
C.PER,
C.IS_,
CCP.CLT,
SAPA1.PRO,
SAPA1.SES

FROM SESSION_ALL SA

LEFT JOIN (SELECT 
        SA.SES,
        SA.CLT,
        SAPA.SES,
        SAPA.PRO
        ,RANK() OVER (PARTITION BY SA.SES ORDER BY SAPA.SES DESC) RNK
        FROM  SA
        INNER JOIN SAPA ON SA.SES = SAPA.SES
        WHERE 1=1               
          AND SAPA.PRO IN (61,62)                         
          AND SA.FUL >= TO_DATE('1/1/2013','MM/DD/YYYY')
                                                           )SAPA1 

             ON SA.SES      = SAPA1.SES AND SAPA1.RNK = 1   
 INNER JOIN TN    ON SA.SES    = TN.SES                           
 INNER JOIN CCP   ON SA.CLT    = CCP.CLT
 INNER JOIN C     ON CCP.CLI   = C.CLI
 INNER JOIN CP    ON CCP.CLI   = CP.CLI                                     

WHERE 1=1
 AND C.PER IS NOT NULL
AND SUBSTR(C.HEA,1,1) = 'H'
AND CP.CLI = 1
AND SA.PRO <> 'MMA'
AND SA.FUL >= CCP.STA
AND SA.FUL < NVL(CCP.END('9/9/9000','MM/DD/YYYY'))
AND SA.FUL >= TO_DATE('1/1/2013','MM/DD/YYYY')
AND SA.FUL <= SYSDATE                               
         )

当我从两者中删除计数时,他们都很快回来了。当我添加第二个查询不返回结果的计数时,它就会继续运行。非ANSI(第一个查询)非常快速地返回结果。不知道为什么会这样?我不熟悉执行计划

执行计划第一查询:(非ANSI) enter image description here

执行计划第二次查询:(新) enter image description here

1 个答案:

答案 0 :(得分:0)

我很确定你可以大大简化这些查询。

以下查询应该为您提供与第二个查询完成时相同的计数。我认为您根本不需要SAPA1内联视图,因为您正在计算SA.SES和外部加入SAPA1。您也可以只计算行数(使用count(*)),因为您正在尝试计算的列内部连接(这会自动删除空值)。

尝试一下,看看你得到了什么。除非你使用这些表格向我提供一些虚拟数据,否则我无法自己测试。

select count(*)

FROM SESSION_ALL SA

 INNER JOIN TN    ON SA.SES    = TN.SES                           
 INNER JOIN CCP   ON SA.CLT    = CCP.CLT
 INNER JOIN C     ON CCP.CLI   = C.CLI
 INNER JOIN CP    ON CCP.CLI   = CP.CLI                                     

WHERE C.PER IS NOT NULL
AND SUBSTR(C.HEA,1,1) = 'H'
AND CP.CLI = 1
AND SA.PRO <> 'MMA'
AND SA.FUL >= CCP.STA
AND SA.FUL < NVL(CCP.END('9/9/9000','MM/DD/YYYY'))
AND SA.FUL >= TO_DATE('1/1/2013','MM/DD/YYYY')
AND SA.FUL <= SYSDATE 

以下是第一个查询在相同格式中的外观。虽然我个人更喜欢ANSI连接。

SELECT count(*)
 FROM 
     sa, tn, ccp, cp, c
 WHERE 
     sa.ses = tn.ses
     AND ccp.cli = c.cli
     AND c.cus = sa.pro
     AND substr(c.hea,1,1) = 'H'
     AND sa.ful >= ccp.sta
     AND sa.ful < nvl(ccp.end('9/9/9000','mm/dd/yyyy'))
     AND sa.ful >= to_date('1/1/2013','mm/dd/yyyy')
     AND sa.ful <= sysdate
     AND ccp.cli = cp.cli
     AND cp.clie = 1
     AND sa.proj <> 'MMA'
     AND c.pers IS NOT NULL