I asked this question few days ago, but it involves a bit deeper answer so it was suggested I create a brand new one, so here it goes...
Disclaimer: I cannot create any custom DB objects (functions, SP's, views etc.), so everything needs to be in-line inside a SQL query.
I'm querying Audit table which for the simplicity of this question has following fields:
AttributeMask
ChangedData
CreatedOn
ObjectId
Each record in a DB may have multiple Audit records associated with it. Every time a change is made to a DB record, it will create a record in the Audit table with specific ObjectID
that will point to the source record, CreatedOn
that will have a DateTime
of the change, AttributeMask
with list of AttributeId's that have been changed when SAVE was executed (note, there may be multiple fields changed at once) and ChangedData
will actually have the data that's been changed (pre-changed values). One field can of course be changed multiple times and if it's the case, multiple Audit records for this field will exist (different CreatedOn
values). I need to find what some (not all) fields from the source record looked like at a specific date.
I can run query below:
select a1.ChangeData as ChangedData1, a1.AttributeMask as AttributeMask2, a2.ChangeData as ChangedData2, a2.AttributeMask as AttributeMask2
from Table1 t
join audit a1 on a1.AuditId =
(select top 1 a.auditid from audit a where a.objecttypecode = 3
and a.objectid = T.ObjectId
and a.AttributeMask like '%,10192,%'
and a.CreatedOn <= '8-16-2018'
order by a1.CreatedOn desc)
join audit a2 on a2.AuditId =
(select top 1 a.auditid from audit a where a.objecttypecode = 3
and a.objectid = T.ObjectId
and a.AttributeMask like '%,10501,%'
and a.CreatedOn <= '8-16-2018'
order by a1.CreatedOn desc)
where t.ObjectID = SomeGuidValue
This query is looking for the latest change to 2 fields (10192
and 10501
) which happened before 8-16-2018
. It returns the following data (I added 3rd record to illustrate all possible cases):
ChangeData1 AttributeMask1 ChangeData2 AttributeMask2
NULL NULL True~~True~1904~~~15.8700000000~4760~30000~590~12000~0~390~1904~False~200~ ,10499,10604,10501,10436,10491,10490,10459,10099,10319,10253,10433,10031,10091,10020,10265,10008,10509,
~True~5.56~~House~~200000~ ,10030,10432,10435,197,10099,10192,198, False~1170~600~0~Complete~True~1770~ ,10501,10091,10008,10020,10570,10499,10253,10715,
~~~~200001~ ,10432,10435,197,10099,10192,198, True~2~True~~0~~~100.0000000000~1~business,96838c4f-e63c-e011-9a14-78e7d1644f78~~0~~~~0~False~~1~ ,10499,10509,10501,10203,10436,10491,10490,10459,10099,10157,10253,10433,10715,10031,10091,10020,10265,10008,10319,10699,
This means that 1st record has change to field 10501
only, 2nd record has change to 10192
only and 3rd record has changes to both 10192
and 10501
fields.
AttributeMask field has comma delimited list of all FieldID's that have been changed (note that it starts and ends with comma).
ChangedData field has tilde
(~) delimited list of data that's been changed. Each entry in AttributeMask
corresponds to entry in ChangedData
. For example, if I wanted to see what data was in 10501 field in 1st record, I would need to determine what entry # 10501
is in AttributeMask
field (it's #3 in the list) and then I would need to find out what data is in entry #3 in ChangedData
field (it's TRUE
) and if I wanted to see what was in 2nd record for Field 10192
I'd see what index it has in AttributeMask
(it's #6) and its corresponding value in ChangedData
field is 2000000
.
I need to somehow extract this data in the same query. I was helped with some samples on how this could be done, but I failed to ask the right question in the beginning (thought it would be simpler than explaining all this).
What I need this query to return is something like this:
ChangeData1 AttributeMask1 ChangeData2 AttributeMask2
NULL NULL TRUE 10501
200000 10192 FALSE 10501
200001 10192 TRUE 10501
I hope this is clear now.