USP_DESIGNATION_GETHIERARCHY
Returns the designations in a hierarchy, or all hierarchies if no designation is specified.
Parameters
Parameter | Parameter Type | Mode | Description |
---|---|---|---|
@ACTIVEONLY | bit | IN | |
@DESIGNATIONID | uniqueidentifier | IN | |
@DESIGNATIONLEVELNAME | nvarchar(100) | IN | |
@DESIGNATIONLEVELTYPEID | uniqueidentifier | IN | |
@LOOKUPID | nvarchar(512) | IN | |
@COMBINEDSEARCH | nvarchar(200) | IN | |
@SORTFIELD | tinyint | IN | |
@SORTDIR | tinyint | IN | |
@DESIGNATIONREPORT1CODEID | uniqueidentifier | IN | |
@DESIGNATIONREPORT2CODEID | uniqueidentifier | IN | |
@PURPOSEID | uniqueidentifier | IN |
Definition
Copy
CREATE procedure [dbo].[USP_DESIGNATION_GETHIERARCHY] (
@ACTIVEONLY bit = 0
,@DESIGNATIONID uniqueidentifier = null
,@DESIGNATIONLEVELNAME nvarchar(100) = null
,@DESIGNATIONLEVELTYPEID uniqueidentifier = null
,@LOOKUPID nvarchar(512) = null
,@COMBINEDSEARCH nvarchar(200) = null
,@SORTFIELD tinyint = null
,@SORTDIR tinyint = null
,@DESIGNATIONREPORT1CODEID uniqueidentifier = null
,@DESIGNATIONREPORT2CODEID uniqueidentifier = null
,@PURPOSEID uniqueidentifier = null
)
as
set nocount on;
--NOTE: this is the nth iteration of generating this result set - it handles very large hierarchies in a matter of seconds
--other, more traditional (or eligant) approaches have failed to perform adequately - please take this into account before
--making changes to this procedure
declare @NOMATCH_MASK tinyint = 0;
declare @ISREQUIREDANCESTOR_MASK tinyint = 1;
declare @MATCHESCRITERIA_MASK tinyint = 2;
declare @ISINHIERARCHY_MASK tinyint = 4;
declare @ROOTLEVEL tinyint = 0;
declare @NOTFOUND bit = 1;
declare @ROOTID1 uniqueidentifier;
declare @ROOTID2 uniqueidentifier;
declare @ROOTID3 uniqueidentifier;
declare @ROOTID4 uniqueidentifier;
declare @ROOTID5 uniqueidentifier;
declare @EMPTY uniqueidentifier = '00000000-0000-0000-0000-000000000000';
set @SORTDIR = COALESCE(@SORTDIR, 0);
if coalesce(@DESIGNATIONID, @EMPTY) <> @EMPTY
select @NOTFOUND = 0
,@ROOTID1 = DESIGNATIONLEVEL1ID
,@ROOTID2 = DESIGNATIONLEVEL2ID
,@ROOTID3 = DESIGNATIONLEVEL3ID
,@ROOTID4 = DESIGNATIONLEVEL4ID
,@ROOTID5 = DESIGNATIONLEVEL5ID
from dbo.DESIGNATION
where ID = @DESIGNATIONID
else
set @NOTFOUND = 0;
set @ACTIVEONLY = COALESCE(@ACTIVEONLY, 0);
--sanitize the search values, adding mask chars at beginning and end so it performs a 'contains' style match
if @DESIGNATIONLEVELNAME is not null
set @DESIGNATIONLEVELNAME = dbo.UFN_TEXTSEARCH_SANITIZE(@DESIGNATIONLEVELNAME, '/', default, default, default);
if @LOOKUPID is not null
set @LOOKUPID = dbo.UFN_TEXTSEARCH_SANITIZE(@LOOKUPID, '/', default, default, default);
if @COMBINEDSEARCH is not null
set @COMBINEDSEARCH = dbo.UFN_TEXTSEARCH_SANITIZE(@COMBINEDSEARCH, '/', default, default, default);
declare @T table (
ID uniqueidentifier unique
,PARENTID uniqueidentifier unique (
ID
,PARENTID
)
,DESIGNATIONLEVELID uniqueidentifier
,ROOTDESIGNATIONLEVELID uniqueidentifier
,[LEVEL] tinyint
,SORTKEY nvarchar(50)
,PATHID nvarchar(180) primary key --this primary key is EXTREMELY important for performance!
,PARENTPATHID nvarchar(180) unique (
PATHID
,PARENTPATHID
)
,SORTVALUE nvarchar(512)
,LEVELNAME nvarchar(512)
,PATHNAME nvarchar(max)
,ISACTIVE bit
,ISREVENUEDESIGNATION bit
,USERID nvarchar(512)
,VANITYNAME nvarchar(512)
,DESIGNATIONREPORT1CODEID uniqueidentifier
,DESIGNATIONREPORT2CODEID uniqueidentifier
,DESIGNATIONLEVELTYPEID uniqueidentifier
,DESIGNATIONLEVELTYPE nvarchar(100)
,DESIGNATIONLEVELTYPEHIERARCHYITEMID uniqueidentifier
,SYSTEMGENERATED bit
,MEETSCRITERIA tinyint unique (
ID
,[LEVEL]
,MEETSCRITERIA
)
);
if @NOTFOUND = 0
begin
insert into @T (
ID
,ROOTDESIGNATIONLEVELID
,PATHID
,PARENTPATHID
,DESIGNATIONLEVELID
,SORTVALUE
,[LEVEL]
,LEVELNAME
,PATHNAME
,ISACTIVE
,ISREVENUEDESIGNATION
,USERID
,VANITYNAME
,DESIGNATIONREPORT1CODEID
,DESIGNATIONREPORT2CODEID
,DESIGNATIONLEVELTYPEID
,DESIGNATIONLEVELTYPE
,DESIGNATIONLEVELTYPEHIERARCHYITEMID
,SYSTEMGENERATED
,MEETSCRITERIA
)
select D.ID
,D.DESIGNATIONLEVEL1ID
,case
when (D.DESIGNATIONLEVEL5ID is not null)
then CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL1ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL2ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL3ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL4ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL5ID, @EMPTY))
when (D.DESIGNATIONLEVEL4ID is not null)
then CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL1ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL2ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL3ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL4ID, @EMPTY))
when (D.DESIGNATIONLEVEL3ID is not null)
then CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL1ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL2ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL3ID, @EMPTY))
when (D.DESIGNATIONLEVEL2ID is not null)
then CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL1ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL2ID, @EMPTY))
else CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL1ID, @EMPTY))
end
,case
when (D.DESIGNATIONLEVEL5ID is not null)
then CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL1ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL2ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL3ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL4ID, @EMPTY))
when (D.DESIGNATIONLEVEL4ID is not null)
then CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL1ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL2ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL3ID, @EMPTY))
when (D.DESIGNATIONLEVEL3ID is not null)
then CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL1ID, @EMPTY)) + CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL2ID, @EMPTY))
when (D.DESIGNATIONLEVEL2ID is not null)
then CONVERT(nvarchar(36), isnull(D.DESIGNATIONLEVEL1ID, @EMPTY))
else null
end
,COALESCE(D.DESIGNATIONLEVEL5ID, D.DESIGNATIONLEVEL4ID, D.DESIGNATIONLEVEL3ID, D.DESIGNATIONLEVEL2ID, D.DESIGNATIONLEVEL1ID)
,case @SORTFIELD
when 1
then CONVERT(nvarchar(512), D.ISACTIVE)
when 2
then D.USERID
when 3
then D.VANITYNAME
when 4
then DLT.DESCRIPTION
when 5
then CONVERT(nvarchar(512), D.ISREVENUEDESIGNATION)
else DL.[NAME]
end
,case
when (D.DESIGNATIONLEVEL5ID is not null)
then 5
when (D.DESIGNATIONLEVEL4ID is not null)
then 4
when (D.DESIGNATIONLEVEL3ID is not null)
then 3
when (D.DESIGNATIONLEVEL2ID is not null)
then 2
else 1
end
,DL.[NAME]
,DL.[NAME]
,D.ISACTIVE
,D.ISREVENUEDESIGNATION
,case
when D.SYSTEMGENERATED = 1
then null
else D.USERID
end
,case
when D.SYSTEMGENERATED = 1
-- SHL BBIS Bug 428630; Returning empty string to not break anything but not start anything either
then ''
else D.VANITYNAME
end
,COALESCE(D.DESIGNATIONREPORT1CODEID, DL.DESIGNATIONREPORT1CODEID)
,COALESCE(D.DESIGNATIONREPORT2CODEID, DL.DESIGNATIONREPORT2CODEID)
,DLT.ID
,DLT.DESCRIPTION
,D.DESIGNATIONLEVELTYPEHIERARCHYITEMID
,D.SYSTEMGENERATED
,case
when (
@DESIGNATIONLEVELTYPEID is null
or DLT.ID = @DESIGNATIONLEVELTYPEID
)
and (
@DESIGNATIONREPORT1CODEID is null
or D.DESIGNATIONREPORT1CODEID = @DESIGNATIONREPORT1CODEID
or (
D.DESIGNATIONREPORT1CODEID is null
and DL.DESIGNATIONREPORT1CODEID = @DESIGNATIONREPORT1CODEID
)
)
and (
@DESIGNATIONREPORT2CODEID is null
or D.DESIGNATIONREPORT2CODEID = @DESIGNATIONREPORT2CODEID
or (
D.DESIGNATIONREPORT2CODEID is null
and DL.DESIGNATIONREPORT2CODEID = @DESIGNATIONREPORT2CODEID
)
)
and (
@ACTIVEONLY = 0
or D.ISACTIVE = 1
)
and (
@DESIGNATIONLEVELNAME is null
or DL.[NAME] like @DESIGNATIONLEVELNAME
)
and (
@LOOKUPID is null
or D.USERID like @LOOKUPID
)
and (
@COMBINEDSEARCH is null
or D.USERID like @COMBINEDSEARCH
or DL.[NAME] like @COMBINEDSEARCH
or (
D.SYSTEMGENERATED = 0
and D.VANITYNAME like @COMBINEDSEARCH
)
or exists (
select ALT.ID
from dbo.DESIGNATIONALTLOOKUPID ALT
where ALT.DESIGNATIONID = D.ID
and ALT.ALTLOOKUPID like @COMBINEDSEARCH
)
)
then @MATCHESCRITERIA_MASK
else @NOMATCH_MASK
end | case
when (
(
@ROOTID1 is null
or D.DESIGNATIONLEVEL1ID = @ROOTID1
)
and (
@ROOTID2 is null
or D.DESIGNATIONLEVEL2ID = @ROOTID2
)
and (
@ROOTID3 is null
or D.DESIGNATIONLEVEL3ID = @ROOTID3
)
and (
@ROOTID4 is null
or D.DESIGNATIONLEVEL4ID = @ROOTID4
)
and (
@ROOTID5 is null
or D.DESIGNATIONLEVEL5ID = @ROOTID5
)
)
and (
@PURPOSEID is null
or D.DESIGNATIONLEVEL1ID = @PURPOSEID
or D.DESIGNATIONLEVEL2ID = @PURPOSEID
or D.DESIGNATIONLEVEL3ID = @PURPOSEID
or D.DESIGNATIONLEVEL4ID = @PURPOSEID
or D.DESIGNATIONLEVEL5ID = @PURPOSEID
)
then @ISINHIERARCHY_MASK
else @NOMATCH_MASK
end
from dbo.DESIGNATION D
inner join dbo.DESIGNATIONLEVEL DL on DL.ID = COALESCE(D.DESIGNATIONLEVEL5ID, D.DESIGNATIONLEVEL4ID, D.DESIGNATIONLEVEL3ID, D.DESIGNATIONLEVEL2ID, D.DESIGNATIONLEVEL1ID)
inner join dbo.DESIGNATIONLEVELTYPE DLT on DL.DESIGNATIONLEVELTYPEID = DLT.ID
update A
set A.PARENTID = D.ID
from @T A
inner join @T D on A.PARENTPATHID = D.PATHID;
--assign sortkey to all rows partitioned by PARENTID
update ALLLEVELS
set ALLLEVELS.SORTKEY = SORTED.SKEY
from @T ALLLEVELS
inner join (
select RIGHT('00000' + CONVERT(nvarchar(5), case @SORTDIR
when 1
then ROW_NUMBER() over (
partition by D.PARENTID order by D.SORTVALUE desc
)
else ROW_NUMBER() over (
partition by D.PARENTID order by D.SORTVALUE
)
end), 5) SKEY
,ID
from @T D
) SORTED on ALLLEVELS.ID = SORTED.ID;
declare @level int = 2;
--now loop thru and inherit values from parents and children
while (@level < 6)
begin
update LEVELTOUPDATE
set LEVELTOUPDATE.SORTKEY = PARENT.SORTKEY + LEVELTOUPDATE.SORTKEY
,LEVELTOUPDATE.PATHNAME = PARENT.PATHNAME + ' \ ' + LEVELTOUPDATE.PATHNAME
--,LEVELTOUPDATE.DESIGNATIONREPORT1CODEID = COALESCE(LEVELTOUPDATE.DESIGNATIONREPORT1CODEID, PARENT.DESIGNATIONREPORT1CODEID)
--,LEVELTOUPDATE.DESIGNATIONREPORT2CODEID = COALESCE(LEVELTOUPDATE.DESIGNATIONREPORT2CODEID, PARENT.DESIGNATIONREPORT2CODEID)
from @T LEVELTOUPDATE
inner join @T PARENT on LEVELTOUPDATE.PARENTID = PARENT.ID
where LEVELTOUPDATE.[LEVEL] = @level;
update LEVELTOUPDATE
set LEVELTOUPDATE.MEETSCRITERIA = LEVELTOUPDATE.MEETSCRITERIA | @ISREQUIREDANCESTOR_MASK
from @T LEVELTOUPDATE
where NOT ((LEVELTOUPDATE.MEETSCRITERIA & (@ISINHIERARCHY_MASK | @MATCHESCRITERIA_MASK)) = (@ISINHIERARCHY_MASK | @MATCHESCRITERIA_MASK)
or (LEVELTOUPDATE.MEETSCRITERIA & @ISREQUIREDANCESTOR_MASK) = @ISREQUIREDANCESTOR_MASK)
--where (LEVELTOUPDATE.MEETSCRITERIA & (@ISREQUIREDANCESTOR_MASK | @ISINHIERARCHY_MASK)) = @NOMATCH_MASK
and LEVELTOUPDATE.[LEVEL] = 6 - @level
and exists (
select top 1 1
from @T CHILD
where CHILD.PARENTID = LEVELTOUPDATE.ID
and (
(CHILD.MEETSCRITERIA & (@ISINHIERARCHY_MASK | @MATCHESCRITERIA_MASK)) = (@ISINHIERARCHY_MASK | @MATCHESCRITERIA_MASK)
or (CHILD.MEETSCRITERIA & @ISREQUIREDANCESTOR_MASK) = @ISREQUIREDANCESTOR_MASK
)
);
set @level = @level + 1;
end
end
select D.ID
,D.DESIGNATIONLEVELID
,D.LEVELNAME
,D.DESIGNATIONLEVELTYPE
,D.ISACTIVE
,D.PARENTID
,D.[LEVEL]
,D.DESIGNATIONLEVELTYPEHIERARCHYITEMID
,(
select count(DESIGNATIONLEVELTYPEHIERARCHYITEM.ID)
from dbo.DESIGNATIONLEVELTYPEHIERARCHYITEM
where DESIGNATIONLEVELTYPEHIERARCHYITEM.PARENTID = D.DESIGNATIONLEVELTYPEHIERARCHYITEMID
) HIERARCHYCHILDCOUNT
,D.DESIGNATIONLEVELTYPE PURPOSETYPE
,D.ISREVENUEDESIGNATION as REVENUEDESIGNATION
,D.VANITYNAME
,D.USERID
,case
when D.SYSTEMGENERATED = 1
then null
else D.PATHNAME
end PATHNAME
,case
when ((D.[LEVEL] - @ROOTLEVEL) > 1)
then 'CATALOG:Blackbaud.AppFx.Fundraising.Catalog.dll,Blackbaud.AppFx.Fundraising.Catalog.IndentLevel' + CONVERT(nvarchar(1), (D.[LEVEL] - @ROOTLEVEL)) + '.png'
else null
end IMAGEKEY
,D.SYSTEMGENERATED
,(
select DESCRIPTION
from dbo.DESIGNATIONREPORT1CODE
where ID = D.DESIGNATIONREPORT1CODEID
) DESIGNATIONREPORT1CODE
,(
select DESCRIPTION
from dbo.DESIGNATIONREPORT2CODE
where ID = D.DESIGNATIONREPORT2CODEID
) DESIGNATIONREPORT2CODE
,D.MEETSCRITERIA
from @T D
where (D.MEETSCRITERIA & (@ISINHIERARCHY_MASK | @MATCHESCRITERIA_MASK)) = (@ISINHIERARCHY_MASK | @MATCHESCRITERIA_MASK)
or (D.MEETSCRITERIA & @ISREQUIREDANCESTOR_MASK) = @ISREQUIREDANCESTOR_MASK
order by SORTKEY
--REVISIT: there is a potential flaw in the filter logic which may include descendants when the criteria is only found in the parent [NAME] (because the child names are built from the parent names) - we want it to
--work this way when locating a descendent, but may not want it to when we locate a ascendent - not sure - this could go either way...