WHERE(一组条件)OR(一组第二个条件)OR ...优雅地写
Posted
技术标签:
【中文标题】WHERE(一组条件)OR(一组第二个条件)OR ...优雅地写【英文标题】:WHERE (set of conditions) OR (set of second conditions) OR ... written elegantly 【发布时间】: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 查询?
感谢您的宝贵时间!
【问题讨论】:
【参考方案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, )
【讨论】:
以上是关于WHERE(一组条件)OR(一组第二个条件)OR ...优雅地写的主要内容,如果未能解决你的问题,请参考以下文章