Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Относится к: SQL Server 2016 (13.x) и более поздние версии
База данных SQL Azure
Управляемый экземпляр SQL Azure
SQL Database в Microsoft Fabric
Чтобы получить последнее (текущее) состояние данных во временной таблице, запросите её так же, как к невременной таблице. Если столбцы PERIOD не скрыты, их значения отображаются в запросе SELECT *. Если указать PERIOD столбцы как HIDDEN, их значения не отображаются в SELECT * запросе. Когда столбцы PERIOD скрыты, ссылайтесь на них конкретно в SELECT предложении, чтобы вернуть их значения.
Для проведения анализа на основе времени используйте FOR SYSTEM_TIME предложение с четырьмя временно-специфическими подпредложениями для запроса данных между текущими и историческими таблицами. Дополнительные сведения об этих предложениях см. в темпоральных таблицах и предложении FROM плюс JOIN, APPLY, PIVOT
AS OF <date_time>FROM <start_date_time> TO <end_date_time>BETWEEN <start_date_time> AND <end_date_time>CONTAINED IN (<start_date_time>, <end_date_time>)ALL
Вы можете указывать FOR SYSTEM_TIME отдельно для каждой таблицы в запросе. Используйте его в общих выражениях таблиц, функциях с таблицьными значениями и сохранённых процедурах. Когда вы используете псевдоним таблицы с темпоральной таблицей, укажите предложение FOR SYSTEM_TIME между именем темпоральной таблицы и её псевдонимом (см. второй пример в разделе «Запрос для определённого времени с использованием вложенного предложения AS OF»).
Запрос о конкретном времени с использованием подчиненного предложения AS OF
Используйте подзапрос AS OF, чтобы восстановить состояние данных таким, каким оно было в любой конкретный момент в прошлом. Вы можете восстановить данные с точностью типа datetime2, который вы указали в определениях столбцов PERIOD.
Используйте AS OF подпредложение с постоянными литералами или переменными, чтобы динамически задать временное условие. Указанные вами значения интерпретируются как UTC-время.
Этот первый пример возвращает состояние dbo.Department таблицы AS OF на определённую дату в прошлом.
-- State of entire table AS OF specific date in the past
SELECT [DeptID],
[DeptName],
[ValidFrom],
[ValidTo]
FROM [dbo].[Department] FOR SYSTEM_TIME
AS OF '2021-09-01 T10:00:00.7230011';
Во втором примере сравниваются значения в интервале между двумя моментами времени для подмножества строк.
DECLARE @ADayAgo AS DATETIME2;
SET @ADayAgo = DATEADD(DAY, -1, SYSUTCDATETIME());
-- Comparison between two points in time for subset of rows
SELECT D_1_Ago.DeptID,
d.DeptID,
D_1_Ago.DeptName,
d.DeptName,
D_1_Ago.ValidFrom,
d.ValidFrom,
D_1_Ago.ValidTo,
d.ValidTo
FROM dbo.Department FOR SYSTEM_TIME
AS OF @ADayAgo AS D_1_Ago
INNER JOIN Department AS d
ON D_1_Ago.DeptID = d.DeptID
AND D_1_Ago.DeptID BETWEEN 1 AND 5;
Используйте представления с подзапросами AS OF в темпоральных запросах
Представления полезны, когда требуется сложный анализ данных на определённый момент времени. Распространённый пример — создание бизнес-отчета сегодня с значениями за предыдущий месяц.
Как правило, у клиентов имеется нормализованная модель базы данных, которая включает в себя множество таблиц со связями по внешнему ключу. Выяснить, как данные из этой нормализированной модели выглядели в определённый момент прошлого, бывает сложно, потому что все таблицы меняются независимо по своей частоте.
В этом случае лучше всего создать представление и применить пункт AS OF ко всему представлению. Этот подход разделяет моделирование слоя доступа к данным и анализ на определённый момент времени, поскольку SQL Server прозрачно применяет предложение AS OF ко всем временным таблицам, участвующим в определении представления. Кроме того, можно объединить темпоральные таблицы с нетемпоральными таблицами в одном представлении, и AS OF применяется только к темпоральным. Если представление не ссылается хотя бы на одну темпоральную таблицу, применение темпоральных запросов к нему завершается ошибкой.
В следующем примере кода создается представление, которое объединяет три темпоральные таблицы: Department, CompanyLocationи LocationDepartments:
CREATE VIEW [dbo].[vw_GetOrgChart]
AS
SELECT [CompanyLocation].LocID,
[CompanyLocation].LocName,
[CompanyLocation].City,
[Department].DeptID,
[Department].DeptName
FROM [dbo].[CompanyLocation]
LEFT OUTER JOIN [dbo].[LocationDepartments]
ON [CompanyLocation].LocID = LocationDepartments.LocID
LEFT OUTER JOIN [dbo].[Department]
ON LocationDepartments.DeptID = [Department].DeptID;
GO
Вы можете выполнить запрос для представления, используя AS OF подзапрос и литерал datetime2.
/* Query view AS OF */
SELECT *
FROM [vw_GetOrgChart] FOR SYSTEM_TIME
AS OF '2021-09-01 T10:00:00.7230011';
Запрос изменений в определенных строках со временем
Временные подзапросы FROM ... TO, BETWEEN ... AND и CONTAINED IN полезны, когда нужно получить все исторические изменения по конкретной строке в текущей таблице (это также называется аудитом данных).
Первые два подусловия возвращают версии строк, которые перекрываются с указанным периодом (то есть те, которые начались до данного периода и закончились после него), в то время как CONTAINED IN возвращает только те, которые существовали в пределах границ указанного периода.
Если вы ищете только версии строк, не актуальные, задавайте запросы напрямую к таблице истории для максимальной производительности. Используйте ALL для запроса текущих и исторических данных без каких-либо ограничений.
/* Query using BETWEEN...AND sub-clause*/
SELECT [DeptID],
[DeptName],
[ValidFrom],
[ValidTo],
IIF (YEAR(ValidTo) = 9999, 1, 0) AS IsActual
FROM [dbo].[Department] FOR SYSTEM_TIME
BETWEEN '2021-01-01' AND '2021-12-31'
WHERE DeptId = 1
ORDER BY ValidFrom DESC;
/* Query using CONTAINED IN sub-clause */
SELECT [DeptID],
[DeptName],
[ValidFrom],
[ValidTo]
FROM [dbo].[Department] FOR SYSTEM_TIME
CONTAINED IN ('2021-04-01', '2021-09-25')
WHERE DeptId = 1
ORDER BY ValidFrom DESC;
/* Query using ALL sub-clause */
SELECT [DeptID],
[DeptName],
[ValidFrom],
[ValidTo],
IIF (YEAR(ValidTo) = 9999, 1, 0) AS IsActual
FROM [dbo].[Department] FOR SYSTEM_TIME ALL
ORDER BY [DeptID], [ValidFrom] DESC;
Анализируйте тенденции в течение определённого временного окна
Чтобы подытожить, как выглядят данные за период, объединяйте FOR SYSTEM_TIME BETWEEN ... AND и GROUP BY агрегируйте функции. Используйте этот метод для описательной статистики и анализа тенденций. Он объединяет все версии строк, которые были активны в течение этого окна, вместо того чтобы восстанавливать состояние на один конкретный момент времени.
Следующий пример вычисляет описательные статистические данные по зарплатам сотрудников в течение определённого временного окна, сгруппированные по отделам. Он использует Employee системную версионную таблицу, определённую в временных таблицах и сценариях использования временной таблицы. Столбец AnnualSalary — это числовой показатель, хорошо подходящий для функций AVG, MIN, MAX и STDEV.
Оговорка FOR SYSTEM_TIME BETWEEN ... AND возвращает все версии строки, перекрывающие период. В результате агрегированные данные включают все значения заработной платы, действовавшие в течение этого периода. При изменении зарплаты сотрудника запрос возвращает несколько версий для этого сотрудника, и каждая версия вносит вклад в агрегаты.
DECLARE @periodStart AS DATETIME2 = '2021-01-01';
DECLARE @periodEnd AS DATETIME2 = '2021-12-31';
SELECT [Department],
AVG([AnnualSalary]) AS AvgSalary,
MIN([AnnualSalary]) AS MinSalary,
MAX([AnnualSalary]) AS MaxSalary,
STDEV([AnnualSalary]) AS SalaryStdDev,
COUNT(*) AS RowVersions
FROM [dbo].[Employee] FOR SYSTEM_TIME
BETWEEN @periodStart AND @periodEnd
GROUP BY [Department]
ORDER BY AvgSalary DESC;