Oracle SQL WITH子句正确用例和性能
我必须执行涉及多个深度连接和复杂谓词的相对复杂的查询,其中结果(和标准)取决于符合条件的可用条目.有一些主要和次要标准涉及,主要是始终应用??,如果结果不满意则进行二次打击.简而言之 >返回N(伪)随机不同客户及其最新文档 但是如果没有足够的不同文档类型或不同客户的文档,请尝试仍然满足N个文档的数量 >通过选择更多其他文档来补偿缺少其他文档类型 我选择声明式(查询)方法而不是命令式(游标和计数器).这就是WITH子句的用武之地.粗略地说,通过使用多个WITH块(CTE),我声明了查询(我喜欢将它们视为ad-hoc视图)来为两种文档类型声明两个不同的目标集.最后,我为最终结果提供了不同CTE的UNION子集,执行一些COUNT次检查以限制金额. 多个CTE相互引用,并在COUNT和NOT EXISTS的上下文中从多个位置引用.我是SQL的新手,偶然遇到了WITH,并选择直观地使用它.这是WITH的正确用例还是反模式?该解决方案如何将性能与以命令式样式实现与游标和计数器相同的功能进行比较?我选择了错误的方法吗?我们正在谈论有数百万条目的表格. 这是整个查询.对不起,我不得不掩盖这些领域的机密性. WITH target_documents AS ( SELECT <Necessary fields> FROM documents l WHERE <Suitable document criteria> ),target_documents_type_1 AS ( SELECT * FROM target_documents WHERE type = 1 ),target_documents_type_2 AS ( SELECT * FROM target_documents WHERE type = 2 ),target_customers AS ( SELECT <Necessary fields> FROM customers a WHERE <Suitable customer criteria> AND EXISTS( SELECT 1 FROM target_documents l WHERE l.customer_id = a.customer_id ) ),target_customers_type_1 AS ( SELECT * FROM target_customers a WHERE EXISTS( SELECT 1 FROM target_documents_type_1 l WHERE l.customer_id = a.customer_id ) AND ROWNUM <= (<N> / 2) ),target_customers_type_2 AS ( SELECT * FROM target_customers a WHERE EXISTS( SELECT 1 FROM target_documents_type_2 l WHERE l.customer_id = a.customer_id ) AND a.customer_id NOT IN ( SELECT customer_id FROM target_customers_type_1 ) AND ROWNUM <= <N> ),-- This is the set,which meets the the primary criteria: -- Contains only distinct customers -- The amount of different document types is balanced as much as possible different_customers_set AS ( SELECT <Necessary fields> FROM target_customers_type_1 a -- rows 0--(<N>/2) amount JOIN target_documents_type_1 l ON (l.customer_id = a.customer_id) WHERE l.create_dt = (SELECT MAX(create_dt) FROM target_documents_type_1 WHERE customer_id = l.customer_id) UNION ALL SELECT <Necessary fields> FROM target_customers_type_2 a -- rows 0--<N> amount JOIN target_documents_type_2 l ON (l.customer_id = a.customer_id) WHERE l.create_dt = (SELECT MAX(create_dt) FROM target_documents_type_2 WHERE customer_id = l.customer_id) AND ROWNUM <= <N> - (SELECT COUNT(*) FROM target_customers_type_1) -- Limit the total to max N rows ) -- Final result: primary criteria result filled with the result of secondary criteria SELECT * FROM different_customers_set UNION ALL SELECT <Necessary fields> FROM target_customers a JOIN target_documents l ON (l.customer_id = a.customer_id AND l.document_id NOT IN (SELECT document_id FROM different_customers_set)) WHERE ROWNUM <= <N> - (SELECT COUNT(1) FROM different_customers_set); 这是WITH子句的正确用法吗?是否有一些明显的性能问题,我应该重构哪些?或者我应该完成所有这些必要的工作?此外,此查询本身定义了一个游标,该游标在循环中重复打开(循环为客户定义了某些条件). 我特别担心的是,优化器如何处理那些WITH块.总是使用最有效的计划(因此与使用游标相比,没有性能损失)? 解决方法使用多个CTE本身并不是坏事,我不时这样做以制作更清晰的代码.这是我确定查询是否符合我的性能标准的一般方法:>写出您认为可以获取所需数据的查询版本.这似乎是显而易见的,但请确保您实际上收集了您想要的所有数据,而没有您不想要的数据. 我很少遇到一种情况,我认为自己“哇,如果没有CTE,这种查询会更好”,尽管我认为几乎每天都相反. (编辑:西安站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |