多表优化oracle sql查询

时间:2016-10-03 12:41:56

标签: sql oracle query-optimization

我知道有关查询的每一个问题都可能有所不同,所以我仍然希望早些时候没有回答这个问题 我正在经过优化的Oracle sql查询,它将扫描多个表。

让我告诉你我的要求:

我们有一个UNIQUEREFERENCE表,我们在参考字段的散列(Varchar)的组合中插入entitykey(我们说A,B和C的3个主要实体),如下所示:

UNIQUEREFERENCEKEY REFERENCENAME REFERENCE IDENTIFIER1 IDENTIFIER2 SEQUENCE ORIGINALAKEY ORIGINALBKEY  ORIGINALCKEY ORIGINALENTITYTYPE ORIGINALDISPLAYENTITYID REFERENCETIME ID3 

现在我必须编写一个不应该从上表中带来任何行的查询,确保3个实体中没有一个具有“已拒绝”或“已取消”状态。如果返回了一些行,那么我们将其视为A或B或C的副本,基于ORIGINALENTITYTYPE。

如果没有返回任何内容,那么我们在此表中插入新引用并继续处理。

到目前为止我的尝试:

 select
            REFERENCENAME as referenceName,
            REFERENCE as reference,
            IDENTIFIER1 as Identifier1,
            IDENTIFIER2 as Identifier2,
            max(SEQUENCE) as maxSequence,
            count(1) as totalCount,
            min(ORIGINALDISPLAYENTITYID) keep (dense_rank first order by sequence ) as firstDisplayId,
            min(ID3) keep (dense_rank first order by sequence ) as firstId3,
            min(case
                    when 'com.example.domain.A' = :checkEntityName and ORIGINALENTITYTYPE = :checkEntityName and ORIGINALAKEY = :checkEntityKey
                        then ORIGINALAKEY
                    when 'com.example.domain.B' = :checkEntityName and ORIGINALENTITYTYPE = :checkEntityName and ORIGINALBKEY = :checkEntityKey
                        then ORIGINALBKEY
                    when 'com.example.domain.C' = :checkEntityName and ORIGINALENTITYTYPE = :checkEntityName and ORIGINALCKEY = :checkEntityKey
                        then ORIGINALCKEY
                    else null
                end) as entityKey
        from UNIQUEREFERENCE
        where REFERENCENAME = :referenceName
            and REFERENCE = :reference
            and NVL(IDENTIFIER2, 'N/A') = NVL(:Identifier2, 'N/A')
            and NVL(IDENTIFIER1, 'N/A') = NVL(:Identifier1, 'N/A')
        group by REFERENCENAME, REFERENCE, IDENTIFIER1, IDENTIFIER2 

正如您所看到的,参数checkEntityName和checkEntityKey将在运行时在所有3个实体的此通用查询中被替换。

现在我只需要从实体表中对3个entityKey进行连接,以确保我们不会考虑那些状态为(“已拒绝”,“已取消”)的实体(A,B和C)并且我不能来到目前为止,还有一个完美的优化查询。

任何帮助都会非常感激,或者在单个SQL查询中解决此问题的任何更好方法。

感谢。

更新:按要求添加样本数据。

UniqueReference表

1 TEST1 XYZ1234 null ABCD SEQ12345 1231 null null com.example.domain.A null  
2 TEST2 XYZ4567 null ABCD SEQ12346 null 2341 null com.example.domain.B null  
3 TEST3 XYZ8910 null ABCD SEQ12347 null null 5671 com.example.domain.C null  

然后是实体表A

s.no  reference   status  
1     XYZ1234     Rejected  
2     XYZ4561     Processed  
3     XYZ7891     Cancelled  

然后是实体表B

s.no  reference   status  
1     XYZ4567     Processed
2     XYZ6561     Processed  
3     XYZ8891     Cancelled  

然后是实体表C

s.no  reference   status  
1     XYZ8910     Cancelled  
2     XYZ8562     Processed  
3     XYZ1789     Cancelled  

从上面的uniquereference数据我不希望在entityType为A或C的情况下返回第1行或第3行,因为A和C的相应引用(XYZ1234,XYZ8910)的状态分别为Rejected / Cancelled。 虽然将返回uniquereference的第2行,因为实体B未被拒绝或取消,因此该引用无法重复使用,并且对于此用例,它将是重复的。

1 个答案:

答案 0 :(得分:0)

我对你使用的一些细节并不完全清楚,但如果我理解正确,这种方法可能会有所帮助:

SELECT UR.reference
     , UR.fieldA
     , UR.fieldB
     , UR.fieldN
     , COUNT(EntityA.sno) +
       COUNT(EntityB.sno) +
       COUNT(EntityC.sno) as subrecords
FROM UniqueReference UR
LEFT JOIN EntityA A
    ON UR.reference = A.reference
    AND A.status = 'PROCESSED'
LEFT JOIN EntityB B
    ON UR.reference = B.reference
    AND B.status = 'PROCESSED'
LEFT JOIN EntityC C
    ON UR.reference = C.reference
    AND C.status = 'PROCESSED'
GROUP BY UR.reference
HAVING subrecords > 0
-- this may need to be: HAVING COUNT(EntityA.sno) + COUNT(EntityB.sno) + COUNT(EntityC.sno) > 0