Вы можете реконструировать записи. Запрос будет немного громоздким. Логика состоит в том, чтобы сделать следующее для данного поля, значение определяется следующими правилами:
- Новое значение записи со следующей меньшей версией, чем @versionnumber
- Старое значение записи со следующей более высокой версией, чем @versionnumber
- Текущее значение
Вот пример (с меньшим количеством полей):
select t1.objId, t1.userId,
max(case when tv.FieldName = 'Data1' and VersionNumber < @VersionNumber
then tv.NewValue
when tv.FieldName = 'Data1' and VersionNumber > @VersionNumber
then tv.OldValue
when tv.FieldName = 'Data1' and VersionNumber is null
then t.Data1
end) as Data1,
max(case when tv.FieldName = 'Data2' and VersionNumber < @VersionNumber
then tv.NewValue
when tv.FieldName = 'Data2' and VersionNumber > @VersionNumber
then tv.OldValue
when tv.FieldName = 'Data2' and VersionNumber is null
then t.Data2
end) as Data2,
. . .
from table1 t1 left outer join
(select tv.*,
row_number() over (partition by objId, userId, fieldname
order by abs(VersionNumber - @VersionNumber)
) as seqnum
from table_var tv
) tv
on tv.objId = t.objId and tv.userId = t.userId and seqnum = 1
group by t1.objId, t1.userId;
Одной из проблем с этой логикой является уверенность в том, что текущее значение не случайно смешивается в предыдущих значениях. А left outer join
с seqnum = 1
обрабатывает это. Текущее значение используется только тогда, когда нет совпадения с предыдущим или последующим значением.