【问题标题】:WHERE (set of conditions) OR (set of second conditions) OR ... written elegantlyWHERE(一组条件)OR(一组第二个条件)OR ...优雅地写
【发布时间】:2017-05-16 12:14:01
【问题描述】:

我有以下问题:

我有一个包含材料属性的 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 查询?

感谢您的宝贵时间!

【问题讨论】:

    标签: sql oracle excel vba


    【解决方案1】:

    你应该可以做到:

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

    【讨论】:

    • 我选择了您的解决方案并实施了它。会不会,如果某些条件为 NULL,这将不起作用?
    • 确实不适用于某些属性为 null - 再说一次,最初问题中描述的 where 子句也是如此。
    • @LucasRaphaelPianegonda 。 . .里克完全正确。这与您问题中的 equals 行为相同。
    • 我纠正自己:我 90% 确定没有 NULL 值,只有空值。您可以想象,例如,拉伸测试具有拉伸速度、温度和材料的测试方向等参数。但是简单的密度测量没有这样的参数。这意味着测试条件有时有值,有时没有值(空)。但它们不是 NULL(未知)。
    【解决方案2】:

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

    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 中创建一个临时表不是那么麻烦,而是无法完成。

    【讨论】:

      【解决方案3】:

      将您的位置放入(临时)表(列: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,以及一个简单的选择来询问它

      【讨论】:

      • 似乎是一个很好的解决方案,但是我不想从这张表中写入数据库。它应该只是一个展示工具,我的想法是让它成为用户的只读工具。通过这种方式,我可以确定用户或错误无法操作数据库上的数据。我会尝试第一个答案,尽管我认为你的答案会更好。
      【解决方案4】:

      除了 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, )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-14
        • 1970-01-01
        • 2014-05-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多