2013-11-04 90 views
1

我知道如何蛮力解决这个问题;我主要是在寻找一个优雅的解决方案来增加我对未来的知识。Oracle SQL:选择多列可以包含多个值的记录

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

天哪,如果您的数据库已正确归一化,那么查询将很容易。说真的,如果这是你正在运行的查询类型,那么你应该有一个'codes'表,每个实体每行一个代码。 –

+0

不幸的是,它不是*我的*数据库。 :)我同意你的观点,数据应该正常化。但是,这是一种商业产品,我拥有只读访问权限。所以没有临时表,不可能修改。 –

回答

1

虽然我@GorndonLinoff同意创建一个code表很可能是“正确”的解决方案,这里有一个技巧,你可以尝试在不改变你的表结构:

如果相关的值已知当你写的查询,可以从dual一套UNION -ized查询取代内嵌列表,然后加入一个你的桌子上,利用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); 

当然,您可以随时用dual替换一系列SELECT s的临时表,但这是基本思路。

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

+0

这个看起来最像我想找的东西。我正在搜索的值都是已知的,虽然8'从双选择比(11或12或24 ...)长一点,但它仍然只提到8个值一次,而20个列在SQL。 –

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)) 
0

也许尝试unpivot的数据(11克):

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。

相关问题