将IN更改为EXISTS

时间:2012-09-09 10:45:32

标签: oracle exists

我有这个2查询:

查询#1

SELECT A1.clrn_id  ,A1.gpgroup ,A1.cl_id
FROM p_dtl A1
WHERE A1.PYMT_DT = TO_DATE(:1 ,'YYYY-MM-DD') 
and A1.clrn_id in (
                     select clrn_id  
                     from gp_cl_rn run  
                     where run.clrn_id = a1.clrn_id 
                     and run.finalized_ind = :2
                  )
                    AND cl_id IN 
                        ( 
                            SELECT cl_id 
                            FROM hm_sal 
                            WHERE oprt_id ='004038'  
                            AND runctrl_id = :3
                        )  

查询#2

SELECT B.eid
FROM JBB B
WHERE B.eid IN 
(
    (
        SELECT eid
        FROM pbank A
        WHERE (bankid,branchid) IN 
        (
            SELECT bankid  ,branchid  
            FROM pbranch 
            WHERE sourceid = :1
            AND estat=:2
        )
        AND ESTAT = :2
        AND acct_type = :3
        AND acct_id = (
                select max(D.acct_id) 
                from pbank D 
                where D.eid = A.eid
                AND D.ESTAT = :2
                AND D.acct_type = :3)
     )
)

如何将第一个查询的clrn_id和第二个查询的B.eid更改为EXISTS函数? bankidbranchidacct_id是否也可以更改为EXISTS函数?

提前致谢!

3 个答案:

答案 0 :(得分:3)

可以将其更改为where exists,但您可能希望改为join

SELECT B.eid
  FROM JBB B
  JOIN ( SELECT eid, estat, acct_type, acct_id
              , max(acct_id) over ( partition by eid ) as max_acct
           FROM pbank 
                ) A
    ON b.eid = a.eid
  JOIN pbranch C
    ON a.bankid = c.bankid
   AND a.branchid = c.brahchid
 WHERE c.sourceid = :1
   AND c.estat = :2
   AND a.ESTAT = :3
   AND a.acct_type = :4
   AND a.acct_id = a.max_acct

通过使用分析函数max(),您无需进行子选择;我认为,以这种方式做事情也更加清晰。


并且,您新添加的查询变为:

SELECT A1.clrn_id, A1.gpgroup, A1.cl_id
  FROM p_dtl A1
  JOIN gp_cl_rn run
    ON A1.clrn_id = run.clrn_id
 WHERE A1.PYMT_DT = TO_DATE(:1 ,'YYYY-MM-DD') 
   AND run.clrn_id = a1.clrn_id 
   AND run.finalized_ind = :2

我注意到您明确使用了to_date()函数,这意味着您将日期存储为字符串。这是不好的做法,可能会在较长时间内给您带来麻烦......如果可能的话,请尽量避免。


max(acct_id) over ( partition by eid ) 

analytic function;这与聚合函数max()完全相同,除了不需要GROUP BY之外,它为结果集中的每个行返回相同的结果。

此特定用途会为每个acct_id返回最大eid。有大量的分析功能,但最好的办法是亲自尝试。还有several examples在线提供。

使用JOIN不一定 where exists更快,它只取决于你所追求的。和所有事情一样,我建议尝试两者并更多地了解适合您的特定情况。

一般来说,它们有不同的用途; where exists旨在当找到满足条件的单行时停止“计算”行。加入,做一切。在你的情况下你想要的一切可能在它们之间选择很少,但我会一直使用JOIN;只需确保您的索引正确。

答案 1 :(得分:2)

我希望,它会对你有所帮助:

SELECT B.eid
FROM JBB B
where exists
(
    SELECT 1
    FROM pbank A
    WHERE exists
        (
            SELECT 1 
            FROM pbranch PB
            WHERE PB.sourceid = :1
            AND PB.estat=:2
            and PB.bankid  = A.bankid
            AND PB.branchid  = A.branchid
        )
        AND ESTAT = :2
        AND acct_type = :3
        AND A.eid = B.eid
        AND acct_id = (
                select max(D.acct_id) 
                from pbank D 
                where D.eid = A.eid
                AND D.eid = B.eid
                AND D.ESTAT = :2
                AND D.acct_type = :3)
)

答案 2 :(得分:1)

SELECT B.eid
FROM JBB B
JOIN
(
    (
        SELECT eid
        FROM pbank A
        WHERE (bankid,branchid) IN 
        (
            SELECT bankid  ,branchid  
            FROM pbranch 
            WHERE sourceid = 'BNIATB'
            AND estat='A'
        )
        AND ESTAT = 'A'
        AND acct_type = 'S'
        AND acct_id = (
                select max(D.acct_id) 
                from pbank D 
                where D.eid = A.eid
                AND D.ESTAT = 'A'
                AND D.acct_type = 'S')
     )
) C on B.eid = c.EID