как создать представление mssql для получения информации о последнем состоянии
-
03-07-2019 - |
Вопрос
допустим, у меня есть две таблицы, одна для записей объектов и одна для записей активности об этих объектах.
я вставляю новую запись в эту таблицу действий каждый раз, когда объект вставляется или обновляется.
чтобы рассказать это простым способом, предположим, что у меня есть четыре поля в таблице действий;Идентификатор объекта, тип, статус и дата.
когда объект вот-вот будет обновлен, я планирую получить последнее состояние объекта и посмотреть на изменения.если есть разница между обновляющимся значением и предыдущим значением, я установлю значение с новыми входными данными, в противном случае я установлю его равным null.так, например, в процессе обновления пользователь изменяет только значение статуса объекта, но оставляет значение типа неизменным, поэтому я вставлю новую строку с нулевым значением для типа и новым значением для статуса.
SELECT * FROM Activity; oid type status date ----------------------------------------- 1 0 1 2009.03.05 17:58:07 1 null 2 2009.03.06 07:00:00 1 1 null 2009.03.07 20:18:07 1 3 null 2009.03.08 07:00:00
итак, я должен создать представление, сообщающее мне о текущем состоянии моего объекта, например,
SELECT * FROM ObjectStateView Where oid = 1; oid type status date ----------------------------------------- 1 3 2 2009.03.08 07:00:00
как мне этого добиться?
Решение
Предполагаемая дата может быть использована для поиска последней записи:
CREATE VIEW foo
AS
SELECT
A.oid,
(SELECT TOP 1 type FROM Activity At WHERE At.OID = A.oid AND At.Date <= MAX(A.date) AND type IS NOT NULL),
(SELECT TOP 1 status FROM Activity Ast WHERE Ast.OID = A.oid AND Ast.Date <= MAX(A.date) AND status IS NOT NULL),
MAX(A.date) AS date
FROM
Activity A
GO
Редактировать:если вы хотите ПРИСОЕДИНИТЬСЯ (непроверенный)
CREATE VIEW foo
AS
SELECT TOP 1
A.oid,
At.type,
Ast.status,
A.date
FROM
Activity A
LEFT JOIN
(SELECT TOP 1 oid, date, type FROM Activity WHERE type IS NOT NULL ORDER BY date DESC) At ON A.OID = At.oid
LEFT JOIN
(SELECT TOP 1 oid, date, status FROM Activity WHERE status IS NOT NULL ORDER BY date DESC) Ast ON A.OID = Ast.oid
ORDER BY date DESC
GO
Следовало добавить это раньше:
Он будет масштабироваться экспоненциально, потому что вам придется прикоснуться к таблице 11 раз подряд.
Лучшим решением было бы поддерживать "текущую" таблицу и поддерживать ее с помощью триггера activity.
Другие советы
Рассматривали ли вы возможность использования МАКС. функция?
select oid, type, status, MAX(date) as max_date
from ObjectStateView
where oid = 1
Не совсем уверен, зачем вам понадобились бы там нули.Вы можете отслеживать, что изменилось между входными данными, сравнивая последнюю запись с предыдущей.Тогда текущее состояние объекта является последней записью в таблице.Вы можете определить, изменился ли объект, создав хэш частей объекта, в которых вы хотите отслеживать изменения, и сохранив его в виде дополнительного столбца.
Исторические ценности:
Поскольку вы отслеживаете изменения, возможно, вам захочется просмотреть статус объекта в историческом порядке:
SELECT a.oid,
a.date,
a_type.type,
a_status.status
FROM Activity a
LEFT JOIN Activity a_type
ON a_type.oid = a.oid
AND a_type.date = (SELECT TOP 1 date FROM Activity WHERE oid = a.oid AND date <= a.date AND type IS NOT NULL ORDER BY date DESC)
LEFT JOIN Activity a_status
ON a_status.oid = a.oid
AND a_status.date = (SELECT TOP 1 date FROM Activity where oid = a.oid AND date <= a.date AND status IS NOT NULL ORDER BY date DESC)
который вернется:
oid date type status
----------- ---------- ----------- -----------
1 2009-03-05 0 1
1 2009-03-06 0 2
1 2009-03-07 1 2
1 2009-03-08 3 2
Учет результатов работы:
С другой стороны, если у вас больше нескольких полей, а таблица большая, производительность может стать проблемой.В этом случае мне также имело бы смысл хранить / кэшировать все значения целиком в другой таблице Мои данные История, который содержал бы данные, подобные приведенной выше таблице.Затем выбрать текущую (последнюю) версию тривиально, используя представление SQL, фильтрующее последнюю строку (только 1 строку) по oid и дате.