Skip to main content

Celonis Product Documentation

LINK_PATH_SOURCE - LINK_PATH_TARGET
Description

The LINK_PATH_SOURCE - LINK_PATH_TARGET operators return tables containing edge data, which are respectively joined to source or target nodes, created by the LINK_PATH operator.

The output of LINK_PATH_SOURCE/LINK_PATH_TARGET is a column containing all edges of all paths contained in the LINK_PATH input parameter. Each row's data corresponds to the value of the traversed edge in the specified mapping table column. The generated columns are joined to LINK_PATH's activity table in a N:1 fashion.

Syntax
 LINK_PATH_SOURCE ( link_path_table.column , mapping_table1.column [, mapping_table2.column ] ... )
 LINK_PATH_TARGET ( link_path_table.column , mapping_table1.column [, mapping_table2.column ] ... )
NULL handling
  • Object Link mapping table entries with NULL values in the IN or OUT column will register the object specified in the none-NULL entry. However, no link will be added to the Object Link graph.

Examples

[1]

LINK_PATH_SOURCE and LINK_PATH_TARGET simply return a column of all involved edges that have been visited during traversal. If the traversal of the Object Link graph does not contain any multi-edges, rows in that column will be joined in a 1:1 fashion with the associated SOURCE or TARGET node in the LINK_PATH table. In general, however, the connection between these tables and the LINK_PATH table is N:1, since there are N possible edges for 1 pair of nodes in the case of multi-edges. Therefore, we usually also don't have a common table between the LINK_PATH_SOURCE/LINK_PATH_TARGET tables.

Object_Link_Cyclic_Multi_Edge_Scenario.png

This example lists all edges that were traversed from the start node A to the end node E in the above graph. Note that the result of this example is independent of whether we use LINK_PATH_SOURCE or LINK_PATH_TARGET, as the outcome of these operators only differs in the join partner with the LINK_PATH table.

Query

Column1

         LINK_PATH_SOURCE ( ACTIVITY_TABLE ( LINK_PATH ( "Case"."ID" , CONSTRAINED BY ( START ( "Case"."ID" = 'A' ) , END ( "Case"."ID" = 'E' ) , WITH CYCLES ) ) ) , "Mapping"."OUT" ) || '->' || LINK_PATH_SOURCE ( ACTIVITY_TABLE ( LINK_PATH ( "Case"."ID" , CONSTRAINED BY ( START ( "Case"."ID" = 'A' ) , END ( "Case"."ID" = 'E' ) , WITH CYCLES ) ) ) , "Mapping"."IN" )
        

Input

Output

Case

ID : string

OBJ_ATTR : int

'A'

0

'B'

1

'C'

2

'D'

3

'E'

1

'F'

1

MAPPING

OUT : string

IN : string

LINK_ATTR : int

'A'

'B'

1

'A'

'B'

2

'B'

'C'

3

'B'

'C'

4

'B'

'C'

6

'B'

'E'

7

'C'

'B'

5

'C'

'D'

8

'F'

'B'

9

Result

Column1 : string

'A->B'

'A->B'

'B->C'

'B->C'

'B->C'

'C->B'

'B->E'

'A->B'

'A->B'

'B->E'

[2]

This example shows how to solve the issue of having multiple edges per pair of nodes. We can see that the result contains NULL values when the target node does not have a join partner in the operators' results. Effectively this means that each end node in the LINK_PATH table is NULL when combined with LINK_PATH_SOURCE and each start node row is NULL if LINK_PATH_TARGET is used.

Query

Column1

         CASE_ID_COLUMN ( LINK_PATH ( "Case"."ID" , CONSTRAINED BY ( START ( "Case"."ID" = 'A' ) , END ( "Case"."ID" = 'E' ) , WITH CYCLES ) ) )
        

Column2

         LINK_PATH ( "Case"."ID" , CONSTRAINED BY ( START ( "Case"."ID" = 'A' ) , END ( "Case"."ID" = 'E' ) , WITH CYCLES ) )
        

Column3

         PU_MIN ( ACTIVITY_TABLE ( LINK_PATH ( "Case"."ID" , CONSTRAINED BY ( START ( "Case"."ID" = 'A' ) , END ( "Case"."ID" = 'E' ) , WITH CYCLES ) ) ) , LINK_PATH_SOURCE ( ACTIVITY_TABLE ( LINK_PATH ( "Case"."ID" , CONSTRAINED BY ( START ( "Case"."ID" = 'A' ) , END ( "Case"."ID" = 'E' ) , WITH CYCLES ) ) ) , "Mapping"."LINK_ATTR" ) )
        

Column4

         PU_MAX ( ACTIVITY_TABLE ( LINK_PATH ( "Case"."ID" , CONSTRAINED BY ( START ( "Case"."ID" = 'A' ) , END ( "Case"."ID" = 'E' ) , WITH CYCLES ) ) ) , LINK_PATH_TARGET ( ACTIVITY_TABLE ( LINK_PATH ( "Case"."ID" , CONSTRAINED BY ( START ( "Case"."ID" = 'A' ) , END ( "Case"."ID" = 'E' ) , WITH CYCLES ) ) ) , "Mapping"."LINK_ATTR" ) )
        

Input

Output

Case

ID : string

OBJ_ATTR : int

'A'

0

'B'

1

'C'

2

'D'

3

'E'

1

'F'

1

MAPPING

OUT : string

IN : string

LINK_ATTR : int

'A'

'B'

1

'A'

'B'

2

'B'

'C'

3

'B'

'C'

4

'B'

'C'

6

'B'

'E'

7

'C'

'B'

5

'C'

'D'

8

'F'

'B'

9

Result

Column1 : int

Column2 : string

Column3 : int

Column4 : int

0

'A'

1

null

0

'B'

3

2

0

'C'

5

6

0

'B'

7

5

0

'E'

null

7

1

'A'

1

null

1

'B'

7

2

1

'E'

null

7

[3]

Since individual paths consist of multiple nodes and these nodes have multiple edges associated with them, we need to resolve two consecutive N:1 connections if we want to relate the edge information to a single path. In this example, we calculate how many paths traverse the same nodes, starting from node A. Before we multiply the numbers of available edges between adjacent nodes, we have to explicitly ignore 0 counts by setting them to NULL.

Query

Column1

         VARIANT ( LINK_PATH ( "Case"."ID" , CONSTRAINED BY ( START ( "Case"."ID" = 'A' ) ) ) )
        

Column2

         PU_PRODUCT ( CASE_TABLE ( LINK_PATH ( "Case"."ID" , CONSTRAINED BY ( START ( "Case"."ID" = 'A' ) ) ) ) , REMAP_INTS ( PU_COUNT ( ACTIVITY_TABLE ( LINK_PATH ( "Case"."ID" , CONSTRAINED BY ( START ( "Case"."ID" = 'A' ) ) ) ) , LINK_PATH_SOURCE ( ACTIVITY_TABLE ( LINK_PATH ( "Case"."ID" , CONSTRAINED BY ( START ( "Case"."ID" = 'A' ) ) ) ) , "Mapping"."OUT" ) ) , [ 0 , NULL ] ) )
        

Input

Output

Case

ID : string

OBJ_ATTR : int

'A'

0

'B'

1

'C'

2

'D'

3

'E'

1

'F'

1

MAPPING

OUT : string

IN : string

LINK_ATTR : int

'A'

'B'

1

'A'

'B'

2

'B'

'C'

3

'B'

'C'

4

'B'

'C'

6

'B'

'E'

7

'C'

'B'

5

'C'

'D'

8

'F'

'B'

9

Result

Column1 : string

Column2 : int

'A, B, C, D'

6

'A, B, E'

2

See also: