WHERE(条件组)OR(第二组条件)或......优雅地写

时间:2017-05-16 12:14:02

标签: sql oracle excel-vba vba excel

我有以下问题:

我有一个带有Material Properties的Oracle数据库,我正在为它开发Excel-VBA的前端。

有一个视图ALL_TESTS,它代表我要从中加载数据表中所有属性的整个表。确切地说,我得到了一个属性列表,每个属性在特定条件下使用特定条件进行测量,并带有样本状态。对于公司的一个材料我总是希望加载整个包装。

如果我愿意这样做:

SELECT * FROM ALL_TESTS WHERE COMPANY in (Company1, Company2, ...)
                        AND MATERIAL (Material1,Material2, ... )
                        AND Test in (Test1,Test2, ...)
                        AND Property in (Property1, Property2, ...)
                        AND Condition in (Condition1, Condition2, ...)
                        AND State in (State1,State2, ...)

我不仅会获得我想要的测试,还会记录索引彼此不匹配的位置。例如,当记录与company1,material2,test3,property4和State2匹配时。但这不是我想要的,我想要以下内容:

SELECT * FROM ALL_TESTS WHERE (COMPANY = Company1
                        AND MATERIAL = Material1
                        AND Test = Test1
                        AND Property = Property1
                        AND Condition = Condition1
                        AND State = State1)

                        OR (COMPANY = Company2
                        AND MATERIAL = Material2
                        AND Test = Test2
                        AND Property = Property2
                        AND Condition = Condition2
                        AND State = State2)
                        OR ...

我有一种方法可以用更优雅的方式编写它,然后只构建一个超长的SQL查询吗?

感谢您的时间!

4 个答案:

答案 0 :(得分:7)

你应该可以这样做:

SELECT *
FROM ALL_TESTS
WHERE (COMPANY, MATERIAL, Test, Property, Condition, State) IN
          ( (Company1, Material1, Test1, Property1, Condition1, State1),
            (Company2, Material2, Test2, Property2, Condition2, State2)
          )

答案 1 :(得分:0)

如果您拥有另一个表中匹配公司的数据,那么您可以进行简单的连接并获得结果:

SELECT at.*
FROM ALL_TESTS
INNER JOIN MATCHING_COMPANIES mc
    ON at.COMPANY   = mc.COMPANY AND
       at.MATERIAL  = mc.MATERIAL AND
       at.Test      = mc.Test AND
       at.Property  = mc.Property AND
       at.Condition = mc.Condition AND
       at.State     = mc.State

当然,这需要一个单独的表,但是在Oracle或VBA中创建一个临时表可能不会有太多麻烦。

答案 2 :(得分:0)

将你的位置放在(临时)表中(列:MATERIAL,Test,Property,Condition,State),将可能的值插入其中(每个OR都是一行),然后将此表内连接到原始表(ALL_TESTS) ),临时表中的所有列如:

Select *
from ALL_TESTS
inner join temp1 on ALL_TESTS.MATERIAL = temp1.MATERIAL 
AND ALL_TESTS.Test = temp1.Test
AND ALL_TESTS.Property = temp1.Property
.... all other columns 

所以你可以在temp1中有很多行,所有不同的OR,以及一个简单的选择来询问它

答案 3 :(得分:0)

除了Gordon的解决方案,我可以建议使用带有自定义比较逻辑的oracle对象类型来处理NULL比较问题:

CREATE OR REPLACE TYPE test_obj as object(
  company varchar2(100),
  material varchar2(100),
  property varchar2(100),
  condition varchar2(100),
  map member function get_unique_key return varchar2  
)
/

CREATE OR REPLACE TYPE BODY test_obj as 
  map member function get_unique_key return varchar2
  as
  begin
    return nvl(company,'?')||'|'||nvl(material,'?')||'|'||nvl(property,'?')||'|'||nvl(condition,'?');
  end;  
end;
/

DROP TABLE all_tests;

CREATE TABLE all_tests
(
  test          VARCHAR2(100),
  test_obj      TEST_OBJ
)
;

insert into all_tests
select 'TEST1', test_obj('XXX', null, 'test', null)
  from dual 
;

select * from all_tests
where test_obj = test_obj('XXX', null, 'test', null);
TEST     TEST_OBJ
------   --------------
TEST1    (XXX, , test, )