我有一个带有id的表,我需要检查是否有2个条件适用。每个条件都是where子句的集合。
例如,Table1是我需要检查的。
第一个条件:
select t1.id
from table1 t1, table2 t2, table3 t3
where
condition1,
condition2,
condition3
第二个条件:
select t1.id
from table1 t1, table2 t2, table4 t4
where
condition1,
condition4,
condition5
现在我需要检查第一个条件或第二个条件是否适用于同一个id或两者。我被告知使用union并在select语句中为每个条件添加一个静态值(对于第一个条件select t1.id, 1
和第二个条件select t1.id, 2
),但是当我尝试它时,每一行都是单独返回同一个table1 id。
这些表真的很大,包含数百万条记录,所以我需要在一个sql中执行此操作以获得更好的性能,而且我从C代码访问结果,因为我不确定返回的结果数量,我单独执行每个查询会产生非常糟糕的性能,将结果保存在每个查询的数组中,并在每个数组上执行循环以检查两个id或一个条件是否适用,因为将根据哪些条件对每个id进行不同的处理适用于它。
修改的 例如:
t1 ids: 1, 2, 3, 4
for id = 1, only condition 1 apply
for id = 2, only condition 2 apply
for id = 3, both conditions apply
for id = 4, no condition apply
我需要在结果中使用1或2个随机静态标志:
id 1 2
-----------------
1 1
2 2
3 1 2
我知道这听起来很混乱,我甚至不确定是否可以这样做
非常感谢:)
答案 0 :(得分:0)
UPDT
select t1.id as first, ttt.id as second
from table1 t1, table2 t2, table3 t3,
(select t1.id
from table1 t1, table2 t2, table4 t4
where
condition1,
condition4,
condition5) ttt
where
condition1,
condition2,
condition3
答案 1 :(得分:0)
子查询是一种解决方案,但有一种更优雅(虽然鲜为人知)的方法:intersect
子句。它的工作方式与union
类似,但是交叉而不是联合。
select t1.id
from table1 t1, table2 t2, table3 t3
where
condition1,
condition2,
condition3
intersect
select t1.id
from table1 t1, table2 t2, table4 t4
where
condition1,
condition4,
condition5
以类似的方式,minus
可用于查找仅出现在第一个查询中的记录。
select t1.id
from table1 t1, table2 t2, table3 t3
where
condition1,
condition2,
condition3
minus
select t1.id
from table1 t1, table2 t2, table4 t4
where
condition1,
condition4,
condition5
(交换查询以查找仅出现在第二个查询中的查询)
要在一个查询中获取所有内容,您必须使用完整的外部联接:
with q1 as (
select t1.id
from table1 t1, table2 t2, table3 t3
where
condition1,
condition2,
condition3),
q2 as (
select t1.id
from table1 t1, table2 t2, table4 t4
where
condition1,
condition4,
condition5
)
select nvl(q1.id, q2.id) as id,
case when q1.id is not null then 1 else null end "1",
case when q2.id is not null then 2 else null end "2"
from q1 full outer join q2 on q1.id = q2.id
答案 2 :(得分:0)
我认为这是显式连接的情况,例如像这样:
select
t1.id,
case when t2a.id is not null and t3.id is not null then 1 end condition_1st,
case when t2b.id is not null and t4.id is not null then 1 end condition_2nd
from table1 t1
left join table2 t2a on condition2
left join table3 t3 on condition3
left join table2 t2b on condition4
left join table4 t4 on condition5
where contition1
答案 3 :(得分:0)
似乎无论哪种查询,标记行已经或未满足一个或多个条件的最佳方法是使用case语句...
select id,
case when condition1 then 1 else 0 end met_condition1,
case when condition2 then 1 else 0 end met_condition2
from my_table
where condition1 or
condition2
编辑:
这个公式通常是我对(query1 union query 2)方法的首选,因为优化器可以选择将“condition_1或condition_2”转换为union(all)查询,但我不记得它能够转换在相反的方向。
此外,优化者并不总是善于识别条件是否相互排斥,这将允许UNION ALL而不是UNION,并且您可能会背负不必要的UNION驱动的DISTINCT操作。
优化器当然并不总是正确的,但动态采样可能会对决策产生强烈的积极影响,特别是在行有时可以匹配两种情况的情况下。
另一个编辑:
我刚刚想到,在过去,条件1和条件2可以用单独的索引和来满足,结果集中有一定程度的重叠,我对查询有很好的体验。形式......
select ...
from ...
where rowid in (
select rowid
from ...
where condition_1
union
select rowid
from ...
where condition_2)
如果有其他条件适用,无论条件1和条件2如何,并且还将数据集减少了合理数量,那么它也会有所帮助......
with baseline as (
select ...
from ...
where common_condition_set)
select ...
from baseline
where condition_1 or condition_2
或
with baseline as (
select ...
from ...
where common_condition_set)
select ...
from baseline
where condition_1
union
select ...
from baseline
where condition_2
答案 4 :(得分:0)
这是一个单一的查询,可以在合理的时间内完成您想要的任务:
with tmp1 as (
select t1.id
from table1 t1, table2 t2, table3 t3
where
condition1,
condition2,
condition3
), tmp2 as (
select t1.id
from table1 t1, table2 t2, table4 t4
where
condition1,
condition4,
condition5
)
select distinct t1.id, t2.cond as cond1, t3.cond as cond2
from table1 t1, tmp1 t2, tmp2 t3
where t1.id = t2.id(+)
and t1.id = t3.id(+)
and not (t2.cond is null and t3.cond is null)
;
注意:这与ammoQ(更优雅)全外连接答案非常相似。