Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Friday, July 22, 2016 4:37 PM
I am trying to create an audit report from CRM 2011 data. I am pulling all of the info I need, but I'm having trouble doing a CROSS APPLY while maintaining the positional relationship. What I mean is, values 447,446,33 are related to the corresponding ChangeData 1~0~SOME RELATED STRING DATA (see example below).
When I use CROSS APPLY on both columns, I am getting "duplicate" rows
What I have in the Raw data
TransactionID |
AttributeMask |
ChangeData |
50B6B544-674F-E611-8DD5-005056B51407 |
,447,446,33, |
1~0~SOME RELATED STRING DATA |
What I get when I try to use CROSS APPLY
TransactionID |
AttributeMask |
ChangeData |
50B6B544-674F-E611-8DD5-005056B51407 |
33 |
0 |
50B6B544-674F-E611-8DD5-005056B51407 |
33 |
1 |
50B6B544-674F-E611-8DD5-005056B51407 |
33 |
SOME RELATED STRING DATA |
50B6B544-674F-E611-8DD5-005056B51407 |
446 |
0 |
50B6B544-674F-E611-8DD5-005056B51407 |
446 |
1 |
50B6B544-674F-E611-8DD5-005056B51407 |
446 |
SOME RELATED STRING DATA |
50B6B544-674F-E611-8DD5-005056B51407 |
447 |
0 |
50B6B544-674F-E611-8DD5-005056B51407 |
447 |
1 |
50B6B544-674F-E611-8DD5-005056B51407 |
447 |
SOME RELATED STRING DATA |
What I need
TransactionID |
AttributeMask |
ChangeData |
50B6B544-674F-E611-8DD5-005056B51407 |
447 |
1 |
50B6B544-674F-E611-8DD5-005056B51407 |
446 |
0 |
50B6B544-674F-E611-8DD5-005056B51407 |
33 |
SOME RELATED STRING DATA |
This isn't pretty because I'm working through this issue, but here is the code I'm using
declare @Date1 datetime
, @Date2 datetime
, @ObjectTypeCode int
, @ObjectID varchar(40)
set @Date1 = '07/15/2016 00:00:00.000'
set @Date2 = '07/25/2016 23:59:00.000'
set @ObjectTypeCode = 10185 -- IPM Equipment Master
set @ObjectID = '2F0992DC-95AB-E311-B536-005056B51407'
declare @AttributeMaskTable TABLE
(TransactionID varchar(40), AttributeMask VARCHAR(8000)--, ChangeData VARCHAR(8000)
)
insert into @AttributeMaskTable select TransactionID, attributemask from Audit
where CreatedOn between @Date1 and @Date2
and ObjectTypeCode = @ObjectTypeCode
and AttributeMask >''
and OBJECTID = @ObjectID
declare @ChangeDataTable TABLE
(TransactionID varchar(40), ChangeData VARCHAR(8000)
)
insert into @ChangeDataTable select TransactionID, ChangeData from Audit
where CreatedOn between @Date1 and @Date2
and ObjectTypeCode = @ObjectTypeCode
and AttributeMask >''
and OBJECTID = @ObjectID
; with AttributeMask AS(
SELECT TransactionID,
LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS AttributeMask
FROM
(
SELECT TransactionID,CAST('<XMLRoot><RowData>' + REPLACE(AttributeMask,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
FROM @AttributeMaskTable
)t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)
)
, ChangeData AS(
SELECT TransactionID,
LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS ChangeData
FROM
(
SELECT TransactionID,CAST('<XMLRoot><RowData>' + REPLACE(ChangeData,'~','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
FROM @ChangeDataTable
)t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)
)
select distinct a.TransactionID ,AttributeMask ,ChangeData
from AttributeMask a
left join ChangeData b
on a.TransactionID = b.TransactionID
where AttributeMask > ''
and a.TransactionID = '50B6B544-674F-E611-8DD5-005056B51407'
I have seen a few situations such as this one: https://www.mssqltips.com/sqlservertip/1958/sql-server-cross-apply-and-outer-apply/ where I might need to use a function. I'm going to chase this rabbit until I get some feedback otherwise. Any help is appreciated.
Sunday, July 24, 2016 10:05 PM
CROSS APPLY builds a Cartesian product. Thus you need to modify you predicates in the CROSS APPLY subquery. So you need a splt function, which also returns the position.
E.g.
CREATE FUNCTION [dbo].[fnSplitString]
(
@string NVARCHAR(MAX) ,
@delimiter CHAR(1)
)
RETURNS @output TABLE
(
position INT IDENTITY(1, 1) ,
splitdata NVARCHAR(MAX)
)
BEGIN
DECLARE @start INT ,
@end INT
SELECT @start = 1 ,
@end = CHARINDEX(@delimiter, @string)
WHILE @start < LEN(@string) + 1
BEGIN
IF @end = 0
SET @end = LEN(@string) + 1
INSERT INTO @output
( splitdata
)
VALUES ( SUBSTRING(@string, @start, @end - @start)
)
SET @start = @end + 1
SET @end = CHARINDEX(@delimiter, @string, @start)
END
RETURN
END
with
DECLARE @Sample TABLE
(
TransactionID UNIQUEIDENTIFIER,
AttributeMask VARCHAR(255),
ChangeData VARCHAR(255)
);
INSERT INTO @Sample
VALUES ( '50B6B544-674F-E611-8DD5-005056B51407', ',447,446,33,', '1~0~SOME RELATED STRING DATA' );
SELECT *
FROM @Sample S
CROSS APPLY [fnSplitString](SUBSTRING(S.AttributeMask, 2, 1024), ',') A
CROSS APPLY [fnSplitString](S.ChangeData, '~') T
WHERE A.position = T.position;
You just need to get rid of that leading comma.