Oracle SQL:选择多列可包含多个值的记录

时间:2013-11-04 17:26:09

标签: sql oracle

我知道如何强行解决这个问题;我主要寻找一种优雅的解决方案,以增加我对未来的知识。

我有一个包含20个代码标志字段的数据表。 (CODE_01,CODE_02,CODE_03,...,CODE_20)

我正在寻找这些代码列的任何包含某些值的记录(例如:11,12,24,141等)

我可以这样做:

Select * from table
where CODE_01 IN (11, 12, 24, 141)
   or CODE_02 IN (11, 12, 24, 141)
   or ...
   or CODE_20 IN (11, 12, 24, 141);

或者像这样:

Select * from table
where 11 IN (CODE_01, CODE_02, ..., CODE_20)
   or 12 IN (CODE_01, CODE_02, ..., CODE_20)
   or 24 IN (CODE_01, CODE_02, ..., CODE_20)
   or 141 IN (CODE_01, CODE_02, ..., CODE_20);

无论是工作还是复制/粘贴练习。我想知道是否有类似的东西:

Select * from table
where (11, 12, 24, 141) IN (CODE_01, CODE_02, ..., CODE_20);

Select * from table
where (CODE_01, CODE_02, ..., CODE_20) IN (11, 12, 24, 141);

理论上我可以连接20个字段并用正则表达式搜索,我想,但我认为这是一个非常低效(和慢)的查询。

由于

3 个答案:

答案 0 :(得分:1)

虽然我同意@GorndonLinoff认为创建一个code表可能是“正确”的解决方案,但这是一个可以在不改变表结构的情况下尝试的技巧:

如果在编写查询时已知相关值,则可以使用UNION中的一组dual化查询替换内联列表,然后将其加入到您的表中,使用IN运算符:

SELECT *
FROM   some_table
JOIN   (SELECT 11 as val FROM dual
        UNION ALL
        SELECT 12 as val FROM dual
        UNION ALL
        SELECT 24 as val FROM dual
        UNION ALL
        SELECT 141 as val FROM dual)
ON     val IN (code_01, code_02, ... code_20);

当然,您始终可以使用临时表替换SELECT中的dual系列,但这是基本概念。

如果你想稍微玩一下,我在SQLFiddle上创建了一个(相当)简化的演示。

答案 1 :(得分:0)

我不知道这会更快,但你可以试试

select * from table t
where exists 
 (Select * From 
   (Select PK, CODE_01 code from table Union 
    Select PK, CODE_02 code from table Union 
    Select PK, CODE_03 code from table Union 
    Select PK, CODE_04 code from table Union 
    ...
    Select PK, CODE_19 code from table Union 
    Select PK, CODE_20 code from table) z
  Where z.PK = t.PK
     And z.code in (11, 12, 24, 141))

...或

select * from table t
  join (Select PK, CODE_01 code Union 
        Select PK, CODE_02 code Union 
        Select PK, CODE_03 code Union 
        Select PK, CODE_04 code Union 
        ...
        Select PK, CODE_19 code Union 
        Select PK, CODE_20 code) z
    On z.PK = t.PK
Where z.code in (11, 12, 24, 141))

答案 2 :(得分:0)

也许尝试取消数据的转换(11g):

with test_data as (
  select 1 as id, 10 as code1, 11 as code2, 12 as code3 from dual
  union all
  select 2 as id, 10 as code1, 14 as code2, 20 as code3 from dual
  union all
  select 3 as id, 10 as code1, 14 as code2, 30 as code3 from dual
)
select distinct id
from test_data t
unpivot (code_value for codes in (code1, code2, code3))
where code_value in (11, 30);

这将返回第1行和第3行的ID。