SELECT t1.member_id ,
SUM(t1.paid_amt) AS paid_amt
FROM
(SELECT DISTINCT fm.member_id,
fc.claim_skey_no,
fc.claim_id,
fc.claim_line_no ,
CASE
WHEN fc.claim_type_cd = 'RX'
THEN NVL(fc.rx_paid_amt,0) -- For RX claims use rx_paid_amt as paid amount
ELSE NVL(fc.approved_amt,0)
END AS paid_amt -- For all other claims use approved_amt
,
CASE
WHEN fc.claim_type_cd = 'RX'
THEN fc.submit_dt --For RX claims use submit_dt as paid date
ELSE NVL(fc.paid_dt,NVL(fc.edi_eob_dt,NVL(fc.eob_run_dt,fc.outsource_vndr_paid_dt)))
END AS paid_dt --For all other claims use paid_dt
FROM dwprod.fct_claim fc ,
dwprod.fct_member fm
WHERE fc.mbr_skey_no = fm.member_skey_no
-- The service_from_dt on the claim must be between the reimbursement time period.
AND fc.service_from_dt BETWEEN '31-MAY-2013' AND '30-Jun-2014'
-- The follwong 2 conditions make sure that the calims selected are final-status (unadjusted)
-- For non-RX claims, the adjust_type_cd must be Null and the dw_backout_tag must be Null or 'N'
-- For RX claims only the dw_backout_tag must be Null or 'N', the adjust_type_cd is ignored
AND
CASE
WHEN fc.claim_type_cd = 'RX'
THEN 1
WHEN fc.claim_type_cd <> 'RX'
AND fc.adjust_type_cd IS NULL
THEN 1
ELSE 0
END = 1
AND NVL(fc.dw_backout_tag,'N') = 'N'
-- The claim must be in an 'Approved' status, indicated by a status_type_cd = 'A'
AND fc.status_type_cd = 'A'
-- QNXT claims must be in a 'PAID' status
-- Non QNXT claims in the warehouse are assumed to be paid - There are no pended RX claims.
AND
CASE
WHEN fc.dw_source_cd <> 'QNXT'
THEN 1
WHEN fc.dw_source_cd = 'QNXT'
AND fc.last_status_nm = 'PAID'
THEN 1
ELSE 0
END = 1
-- Dental claims are excluded
AND fc.dw_source_cd <> 'DBP'
-- Excludes any Medicare Non-RCI claims
AND
CASE
WHEN NVL(fc.program_nm,'OTHER') = 'MEDICAID'
AND NVL(fc.enroll_ratecode,'RCI') IN ('RCII','RCV','RCVII')
THEN 0
ELSE 1
END = 0
-- It Fits! claims are excluded
AND NVL(fc.expense_cat_nm,'Other') <> 'FITNESS'
AND NVL(fc.proc1_skey_no,12345) NOT IN (21586,21588,21589)
--
AND
CASE
WHEN NVL(fc.program_nm,'OTHER') = 'MEDICAID'
AND NVL(fc.enroll_ratecode,'RCI') IN ('RCII','RCV','RCVII')
THEN 1
WHEN EXISTS
(SELECT 1
FROM dwprod.fct_member_enroll me
WHERE fm.member_skey_no = me.mbr_skey_no
AND fc.service_from_dt BETWEEN me.segment_effect_dt AND me.segment_term_dt
AND me.program_nm = 'MEDICAID'
AND me.enroll_ratecode IN ('RCII','RCV','RCVII')
)
THEN 1
ELSE 0
END = 1
) t1
--Where t1.paid_dt < '31-JAN-2014'
GROUP BY t1.member_id
HAVING SUM(t1.paid_amt) > 175000
回答
运行解释计划以查看导致放缓的原因。从我的头顶,这是什么“杀”你:
WHEN EXISTS
(SELECT 1
FROM dwprod.fct_member_enroll me
WHERE fm.member_skey_no = me.mbr_skey_no
AND fc.service_from_dt BETWEEN me.segment_effect_dt AND me.segment_term_dt
AND me.program_nm = 'MEDICAID'
AND me.enroll_ratecode IN ('RCII','RCV','RCVII')
)
看看你是否能以某种方式改变这种逻辑存在的东西具有更好的性能。解释计划是必须的!
我同意一个解释计划会大大帮助解决这个性能问题。如果没有这些,我会猜想问题的另一部分是谓词太复杂,甲骨文无法正确估计。这导致基数估计较差,ROWS = 1,其中有数百或数十亿行返回。然后导致NESTED LOOP而不是HASH JOIN。有了这样复杂的谓词,可能不会有一个好方法将优化器推向正确的方向。这可能需要像'/ * + use_hash(fc fm)full(fc)full(fm)* /'这样的提示。 –
我同意!在解释计划之后,您可以看到优化器的功能,然后使用Oracle提示来提高性能。我看到优化器做了很不合理的决定(完全是嵌套循环而不是散列连接),并且一个简单的提示已经将查询从大约30分钟改善到了大约1分钟... – Koshera
FROM dwprod.fct_claim fc ,
dwprod.fct_member fm
WHERE fc.mbr_skey_no = fm.member_skey_no
这个交叉连接实际上是一个内部连接。我不能说甲骨文是否会优化这一点,但我们没有理由不使自己的工作更轻松:
FROM dwprod.fct_claim fc ,
INNER JOIN dwprod.fct_member fm
ON fc.mbr_skey_no = fm.member_skey_no
我更喜欢ANSI语法,并且相信它会提高性能从长远来看,通过使查询更易于理解和调试。但对于这个具体的陈述,我认真地怀疑这将有助于表现。无论如何,Oracle将大多数ANSI语法转换为旧式语法。 –
我更喜欢ANSI,但不是在12c中,因为使用这种方式有一个开放的错误。由于12c在外连接方面有一些增强,与旧版本相比,SQL的处理方式不同。看这里http://stackoverflow.com/questions/19686262/query-featuring-outer-joins-behaves-differently-in-oracle-12c – SriniV
我会做一个半盲猜这里,基于DW I”类似的查询与...合作。 Oracle的优化被容易被混淆的谓词如:
where (case when ... then ... else ... end) = 1;
的原因是,甲骨文在严重估计选择性。 像其他人说的那样查看解释计划。如果您发现表dwprod.fct_claim
的估计基数看起来太低,请尝试展开case语句。
例如,而不是:
AND CASE WHEN fc.dw_source_cd <> 'QNXT' THEN 1
WHEN fc.dw_source_cd = 'QNXT' AND fc.last_status_nm = 'PAID' THEN 1
ELSE 0
END = 1
写:
and ( fc.dw_source_cd <> 'QNXT'
or (fc.dw_source_cd = 'QNXT' and fc.last_status_nm = 'PAID')
)
最后说明。这在版本11中似乎不太成问题,但我还没有时间去调查原因。
- 1. 查询运行速度太慢
- 2. Oracle - 查询运行速度很慢
- 3. 查询查询运行速度比直接查询慢 - 在Oracle
- 4. CoreNLP运行速度太慢
- 5. MySQL查询速度太慢或超时
- 6. Parse.com查询速度太慢,需要更快
- 7. 如何优化运行速度太慢的查询(LEFT JOIN)
- 8. 查询运行速度非常慢
- 9. SharePoint库查询运行速度很慢
- 10. 查询运行速度很慢
- 11. SSRS SQL查询运行速度慢
- 12. MySQL中运行速度慢的查询
- 13. 合并查询运行速度很慢
- 14. 加入Oracle时查询速度慢,分裂成两个查询时速度快
- 15. Linq查询运行缓慢,但查询运行速度很快
- 16. 的MySQL查询速度太慢
- 17. 实体框架查询速度太慢
- 18. R循环运行速度太慢
- 19. java - system.nanoTime()运行速度太慢
- 20. 函数运行速度太慢
- 21. Grails标准运行速度太慢
- 22. CROSS APPLY运行速度太慢 - TSQL
- 23. Oracle Bind查询速度很慢
- 24. SQL查询在大数据集上运行但速度很慢?
- 25. Oracle:复杂查询的查询速度非常快,查询速度非常慢
- 26. Matlab执行速度太慢
- 27. PHP查询加载速度太慢。如何加快速度?
- 28. 程序运行速度太慢,输入较大 - C
- 29. 慢速查询...需要更快
- 30. SQLite查询比MSAccess查询运行速度慢10倍
我试过用这个(FROM dwprod.fct_claim fc,INNER JOIN dwprod.fct_member fm ON fc.mbr_skey_no = fm.member_skey_no)仍然需要很长时间。 – user3357343
您是否检查了EXPLAIN PLAN?如果不是,为什么不呢? –
尽管对您的问题没有多大意义,但'AND FC.SERVICE_FROM_DT BETWEEN '31 -MAY-2013'和'30 -JUN-2014''应该是AND AND FC.SERVICE_FROM_DT之间的TO_DATE('31 -MAY-2013' ,'DD-MON-YYYY')和TO_DATE('30 -JUN-2014','DD-MON-YYYY')' – SriniV