Oracle SQL查询优化:如何正确组合非空AND/OR条件过滤空值
解决行转列后的空值过滤与查询性能问题
首先,你的核心问题出在两个关键地方:表关联逻辑错误导致大量无效数据笛卡尔积,以及WHERE子句的逻辑优先级与条件写法错误。我们一步步来修正:
1. 先梳理正确的表关联关系
根据你的描述,三张表的合理关联逻辑应该是:
directory.dataid关联attribute2table中的数据ID字段(你原来写的attribute2table.id = directory.dataid大概率是笔误——attribute2table存储多条属性数据,id应该是自身主键,而非关联directory的dataid,这里假设关联字段是a2.data_id)attribute2table的属性标识字段(比如a2.attr_id)关联attribute1table.attrid,用来对应属性名(比如attrid=2对应LastName)
2. 正确实现行转列并过滤
我们用聚合函数结合CASE WHEN实现行转列,直接把同一DataID的属性合并成一行,避免重复行和空值问题,再通过HAVING子句过滤目标条件:
SELECT d.name, d.dataid, MAX(CASE WHEN a1.attrid = 2 THEN a2.stringval END) AS LastName, MAX(CASE WHEN a1.attrid = 3 THEN a2.stringval END) AS FirstName FROM directory d JOIN attribute2table a2 ON d.dataid = a2.data_id -- 修正数据关联字段 JOIN attribute1table a1 ON a2.attr_id = a1.attrid -- 修正属性关联逻辑 WHERE d.dataid = 1290 AND a2.stringval IS NOT NULL GROUP BY d.name, d.dataid HAVING MAX(CASE WHEN a1.attrid = 2 THEN a2.stringval END) IS NOT NULL OR MAX(CASE WHEN a1.attrid = 3 THEN a2.stringval END) IS NOT NULL;
3. 原来的查询问题解析
- 关联逻辑错误:你之前的
attribute1table.id = directory.dataid完全不符合业务逻辑,会导致两张表错误匹配,产生海量无效笛卡尔积数据,这也是添加OR条件后查询极慢的核心原因。 - 子查询写法问题:SELECT中的子查询没有关联当前行字段,导致每行都返回全局MAX值,出现重复行;WHERE中的子查询也是全局查询,和当前行无关,逻辑完全失效。
- 条件优先级问题:即使忽略关联错误,
AND (...) OR (...)的优先级会让条件变成(directory.dataid=1290 AND stringval IS NOT NULL AND 子查询2非空) OR (子查询3非空),这会拉进其他dataid的数据,不符合你的需求。
4. 预期结果
上述查询会先聚合同一dataid的属性,把LastName和FirstName合并到同一行,再过滤出至少有一个属性非空的行,最终得到你想要的结果:
Name DataID LastName FirstName File10 1290 Doe Jane
内容的提问来源于stack exchange,提问作者NBB
相关产品推荐
相关产品推荐

