Oracle SELECT 对多列有多个 AND 条件(INTERSECT 替代)

Oracle SELECT with multiple AND conditions for multiple columns (INTERSECT alternative)

如何解决以下问题:

假设我们有一座大型建筑物,大约有 100 个温度读取器,每个读取器每分钟收集一次温度。

我有相当大的 table (~100m) 行,其中包含以下列:

Table 临时事件:

 Timestamp   - one entry per minute
 Reader ID   - about 100 separate readers
 Temperature - Integer (-40 -> +40)

Timestamp 和 Reader ID 是 table 的主键和辅助键。我想执行一个查询,查找所有时间戳,其中
reader_01 = 10 度,
reader_02 = 15 度和
reader_03 = 20 度。

换句话说是这样的:

SELECT Timestamp FROM TempEvents
 WHERE (readerID=01 AND temperature=10)
 AND   (readerID=02 AND temperature=15)
 AND   (readerID=03 AND temperature=20)

==> 生成时间戳列表:

Timestamp::
2016-01-01 05:45:00
2016-02-01 07:23:00
2016-03-01 11:56:00
2016-04-01 23:21:00

上面的查询 returns 没有任何内容,因为一行没有同时包含所有条件。在条件之间使用 OR 也不会产生预期的结果,因为所有读取器都应该匹配条件。

使用 INTERSECT,我可以通过以下方式得到结果:

SELECT * FROM
(SELECT Timestamp FROM TempEvents WHERE readerID=01 AND temperature=10
 INTERSECT SELECT Timestamp FROM TempEvents WHERE readerID=02 AND temperature=15
 INTERSECT SELECT Timestamp FROM TempEvents WHERE readerID=03 AND temperature=20
 )
GROUP BY Timestamp ORDER BY Timestamp ASC;

上述查询非常耗时,需要大约 5 分钟才能执行。

有没有更好(更快)的方法得到结果?

如果您要查询的读者数量不是太多,您可以尝试使用 join-查询,例如

select distinct Timestamp
  from TempEvents t1
  join TempEvents t2 using(Timestamp)
  join TempEvents t3 using(Timestamp)
 where t1.readerID=01 and t1.temperature = 10
   and t2.readerID=02 and t2.temperature = 15
   and t3.readerID=03 and t3.temperature = 20

但老实说,我怀疑它的性能是否会比您的 INTERSECT-查询更好。

我刚刚在 Oracle DB 中尝试了这个,它似乎有效:

SELECT Timestamp FROM TempEvents
 WHERE (readerID=01 AND temperature=10)
 OR   (readerID=02 AND temperature=15)
 OR   (readerID=03 AND temperature=20)

确保只更改括号外的 AND

试试这个:

with Q(readerID,temperature) as(
 select 01, 10 from dual
 union all
 select 02,15 from dual
 union all
 select 03,20 from dual
)
select Timestamp FROM TempEvents T, Q
 where T.readerID=Q.readerID and T.temperature=Q.temperature
 group by Timestamp
having count(1)=(select count(1) from Q)

也许这会提供比使用 ORIN 子句更好的计划。