1

好吧,我有一个带有 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和第二个条件的 ex 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

我知道这听起来很乱,我什至不确定是否可以做到

非常感谢 :)

4

5 回答 5

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
于 2012-11-29T11:28:24.903 回答
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 or condition_2”转换为联合(所有)查询,但我不记得它能够在相反的情况下进行转换方向。

此外,优化器并不总是善于识别条件何时互斥,这将允许使用 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
于 2012-11-29T11:39:41.523 回答
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
于 2012-11-29T11:26:34.563 回答
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
于 2012-11-29T11:37:54.667 回答
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 的(更优雅的)完全外连接答案非常相似。

于 2012-11-29T11:54:09.077 回答