Skip to Content
0
Aug 16, 2021 at 12:27 AM

How to query CDS Hierarchy (created with Define Hierarchy) to select all siblings in a CDS

577 Views Last edit Aug 16, 2021 at 04:33 AM 2 rev

Very simple requirement - I'd like to find all work orders against a functional location, or any of it's descendants which is to be exposed as a CDS view.

So here's the recursive relationship of a Functional Location:

@AbapCatalog.sqlViewName: 'YIFLOCHIERREL'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Test'
define view YI_FLOCHierarhcyRelationship as select from I_FunctionalLocation 
  association [0..1] to YI_FLOCHierarhcyRelationship as _Parent
  on  $projection.SuperiorFunctionalLocation = _Parent.FunctionalLocation
{
    key FunctionalLocation,
    SuperiorFunctionalLocation,
    _Parent
}

Now I thought I might be able to use Define Hierarchy to give me the required information - something like this:

define hierarchy YI_FLOCHierarhcy 
  as parent child hierarchy (
    source YI_FLOCHierarhcyRelationship
    child to parent association _Parent    
    siblings order by FunctionalLocation ascending
    orphans root
  )
{
    FunctionalLocation,
    SuperiorFunctionalLocation,
    $node.parent_id as ParentNode,
    $node.node_id as ChildNode,
    $node.hierarchy_is_orphan as HierarchyIsOrphan,
    $node.hierarchy_level as HierarchyLevel,
    $node.hierarchy_rank as HierarchyRank,
    $node.hierarchy_parent_rank as HierarchyParentRank,
    $node.hierarchy_tree_size as HierarchyTreeSize 
}

But then if I try use this, it's unclear from all the doco on how I get the descendents.

e.g. If I use the first CDS view in SQL, it's pretty straightforward for a given Functional Location to get all Descendants.

SELECT 
   FunctionalLocation
 FROM 
  HIERARCHY( source YI_FLOCHierarhcyRelationship 
  child to parent association _parent start where FunctionalLocation = '?0100000000000007264'
    siblings order by functionallocation )


But this SQL can't be put into a CDS view directly, so I'm trying to leverage the Hierarchy CDS view above instead.

Ideally, I'd like to create a CDS association that looks a little like this (making up stuff here) but have no idea of the format - If I query YI_FLOCHierarhcy directly, or via a CDS association, it just returns the 1st level of info.

define view yI_mwhtest as select from I_FunctionalLocation as _Lookup 
  association [0..*] to YI_FLOCHierarhcy as _Hierarchy start where FunctionalLocation = $Projection.FunctionalLocation
 {
   key _Lookup.FunctionalLocation,
   key _Hierarchy.FunctionalLocation,
   
}

If I could do this, I can then I can use this to create another CDS view with association to Work Orders so I can get all Work Orders for a given Functional Location and it's descendants.

Any ideas or examples in S/4HANA 1809 to help here?

Thanks,

Matt

BTW - Here's my temporary dodgy version which has the result I'm after:

@AbapCatalog.sqlViewName: 'YIDODGYHIER'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'FLOC Hierarchy Query'
define view YI_DodgyFLOChiearchy as select from YI_FLOCHierarhcyRelationship as _Root {
    key FunctionalLocation,
    FunctionalLocation as LookupFunctionalLocation
} union all
  select from YI_FLOCHierarhcyRelationship as _Root 
    inner join YI_FLOCHierarhcyRelationship as _First on _Root.FunctionalLocation = _First.SuperiorFunctionalLocation {
  _First.FunctionalLocation,
  _Root.FunctionalLocation as LookupFunctionalLocation 
} union all
  select from YI_FLOCHierarhcyRelationship as _Root 
    inner join YI_FLOCHierarhcyRelationship as _First on _Root.FunctionalLocation = _First.SuperiorFunctionalLocation 
    inner join YI_FLOCHierarhcyRelationship as _Second on _First.FunctionalLocation = _Second.SuperiorFunctionalLocation {
  _Second.FunctionalLocation,
  _Root.FunctionalLocation as LookupFunctionalLocation 
} union all
  select from YI_FLOCHierarhcyRelationship as _Root 
    inner join YI_FLOCHierarhcyRelationship as _First on _Root.FunctionalLocation = _First.SuperiorFunctionalLocation 
    inner join YI_FLOCHierarhcyRelationship as _Second on _First.FunctionalLocation = _Second.SuperiorFunctionalLocation 
    inner join YI_FLOCHierarhcyRelationship as _Third on _Second.FunctionalLocation = _Third.SuperiorFunctionalLocation {
  _Third.FunctionalLocation,
  _Root.FunctionalLocation as LookupFunctionalLocation 
} union all
  select from YI_FLOCHierarhcyRelationship as _Root 
    inner join YI_FLOCHierarhcyRelationship as _First on _Root.FunctionalLocation = _First.SuperiorFunctionalLocation 
    inner join YI_FLOCHierarhcyRelationship as _Second on _First.FunctionalLocation = _Second.SuperiorFunctionalLocation 
    inner join YI_FLOCHierarhcyRelationship as _Third on _Second.FunctionalLocation = _Third.SuperiorFunctionalLocation 
    inner join YI_FLOCHierarhcyRelationship as _Fourth on _Third.FunctionalLocation = _Fourth.SuperiorFunctionalLocation {
  _Fourth.FunctionalLocation,
  _Root.FunctionalLocation as LookupFunctionalLocation 
}