我正在研究资产管理系统的Oracle SQL查询。我的查询使用AMS设备表中的信息更新数据仓库。不幸的是,AMS有点垃圾,而且Equipment表中没有包含最后修改日期,也没有任何方法可以使用审计。
设备表有2,000,000条记录,所以我不想在办公时间内更新整件事。相反,我想将其限制为最近更新的与工作订单相关联的设备。但我还需要在一夜之间更新整个表格,以获取尚未附加到工作订单的任何新记录。我想避免有两个导入,所以我不会遇到一个导入被改变而另一个没有改变的情况。
我所追求的是一种方式,根据一天中的时间,我可以添加额外的连接。
所以在办公时间内会是:
SELECT
*
FROM
Equipment
INNER JOIN
( SELECT DISTINCT Equipment_ID FROM Work_Orders
WHERE Work_Orders.Last_Update > SYSDATE - 2
) WO
ON
Equipment.Equipment_ID = WO.Equipment_ID
但是在晚上9点之后它会是
SELECT
*
FROM
Equipment
我已经在其他地方看到了使用连接的示例,其中ON条件是有条件的,但是我没有找到任何地方甚至连接都是有条件的。这甚至可能吗?
答案 0 :(得分:2)
使用IN子句而不是连接更容易,使用OR允许应用多个条件之一。让我们说你想要选择所有设备"选项在晚上9点到凌晨3点之间启用。你可以这样做:
SELECT
*
FROM
Equipment
WHERE TO_CHAR( SYSDATE, 'HH24' ) > '21'
OR TO_CHAR( SYSDATE, 'HH24' ) < '03'
OR Equipment_ID IN (
SELECT DISTINCT Work_Orders.Equipment_ID FROM Work_Orders
WHERE Work_Orders.Last_Update > SYSDATE - 2
)
答案 1 :(得分:2)
我认为你可以这样做:
SELECT * FROM equipment e
WHERE EXISTS ( SELECT 1 FROM work_orders wo
WHERE wo.equipment_id = e.equipment_id
AND wo.last_update > SYSDATE-2 )
OR TO_CHAR(SYSDATE, 'HH24') BETWEEN '09' and '17'; -- Assuming work hours are 9:00 am to 5:00 pm
现在你在OP中提到这一点:&#34;但是我还需要在一夜之间更新整个表格以获取尚未附加到工作订单的任何新记录。&#34;您可以通过检查日期或检查work_orders
表中是否存在来获取新记录:
SELECT * FROM equipment e
WHERE NOT EXISTS ( SELECT 1 FROM work_orders wo
WHERE wo.equipment_id = e.equipment_id );
将两个查询放在一起,我们可能会得到如下内容:
SELECT * FROM equipment e
WHERE EXISTS ( SELECT 1 FROM work_orders wo
WHERE wo.equipment_id = e.equipment_id
AND wo.last_update > SYSDATE-2 )
OR ( TO_CHAR(SYSDATE, 'HH24') BETWEEN '09' and '17'
AND NOT EXISTS ( SELECT 1 FROM work_orders wo
WHERE wo.equipment_id = e.equipment_id ) );
希望这有帮助。
答案 2 :(得分:1)
我对这个问题的看法。我正在使用和EXISTS构造在WHERE子句中使用OR语句的惰性求值。这样所有条件都是WHERE子句的一部分。
示例数据
create table Equipment
(
Id varchar(3)
);
insert into Equipment values ( 'E01' );
insert into Equipment values ( 'E02' );
create table Orders
(
Num varchar(5),
LastModified date,
EquipmentId varchar(3)
);
insert into Orders values ( 'OR001', SYSTIMESTAMP-4, 'E01' );
insert into Orders values ( 'OR002', SYSTIMESTAMP-3, 'E02' );
insert into Orders values ( 'OR003', SYSTIMESTAMP, 'E01' );
insert into Orders values ( 'OR004', SYSTIMESTAMP, 'E01' );
获取所有适用的设备ID。 在晚上9点之前,OR条件的第一部分失败,并评估下一部分。在晚上9点之后,OR条件的第一部分是有效的(由于懒惰的评估,下一部分不再被验证)。
实际解决方案
select distinct Id
from Equipment
where extract(HOUR from SYSTIMESTAMP) > 21 -- after 9pm do not evaluate the next part of OR condition
or exists ( select 'x'
from Orders
where EquipmentId = Id
and LASTMODIFIED > SYSDATE-2 );
答案 3 :(得分:0)
使用EXTRACT(HOUR FROM CAST(sysdate AS timestamp))
确定一天中的时间。
我决定&#34;工作时间&#34;在下面的例子中是上午9点到下午5点。
SELECT *
FROM CASE
WHEN EXTRACT(HOUR FROM CAST(sysdate AS timestamp)) BETWEEN 9 AND 17
THEN (SELECT *
FROM Equipment e
INNER JOIN (SELECT DISTINCT Equipment_ID
FROM Work_Orders w
WHERE w.Last_Update > SYSDATE - 2) WO
ON e.Equipment_ID = WO.Equipment_ID)
ELSE (SELECT * FROM Equipment)
END