检查一个sql语句中是否由2个不同的“where”子句返回一行

时间:2012-11-29 11:23:18

标签: sql oracle

我有一个带有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

我知道这听起来很混乱,我甚至不确定是否可以这样做

非常感谢:)

5 个答案:

答案 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(更优雅)全外连接答案非常相似。