Я работаю над запросом 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 были условными, однако я не нашел нигде, где даже наличие соединения было бы условным. Это вообще возможно?
Используйте EXTRACT(HOUR FROM CAST(sysdate AS timestamp))
для определения времени суток.
В приведенном ниже примере я определил «рабочее время» с 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
Помещая его в SQL, разработчик говорит, что это не работает (команда SQL неправильно завершилась в строке 3 столбца 11)
Это проще сделать с помощью предложения IN, чем с помощью соединения, используя OR, чтобы разрешить применение одного из нескольких условий. Допустим, вы хотите, чтобы параметр «Выбрать все оборудование» был включен с 21:00 до 3:00. Вы могли сделать это:
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
)
Системе не нравится бит HH24, но вместо него работает EXTRACT. Спасибо!
Я думаю, вы могли бы сделать что-то вроде этого:
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: «Но мне также нужно обновить всю таблицу за ночь, чтобы получить любые новые записи, которые не были прикреплены к рабочим заданиям». Вы можете получить новые записи, проверив дату или проверив наличие в таблице 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 ) );
Надеюсь это поможет.
Системе не нравится бит HH24, но вместо него работает EXTRACT. Спасибо!
К сожалению, вместо одинарных кавычек использовались двойные кавычки - теперь они должны работать без изменений.
Мой взгляд на этот вопрос. Я использую ленивое вычисление оператора OR в предложении WHERE с конструкциями и EXISTS. Таким образом, все условия являются частью предложения 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' );
Получите все применимые идентификаторы оборудования. До 21:00 первая часть условия ИЛИ не выполняется, и выполняется следующая часть. После 21:00 первая часть условия ИЛИ действительна (и из-за ленивой оценки следующая часть больше не проверяется).
Актуальное решение
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 );
Я не думаю, что
CASE
можно использовать в этой позиции в заявленииSELECT
.