diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/ParticipantTaskAssignment.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/ParticipantTaskAssignment.java
new file mode 100644
index 0000000000000000000000000000000000000000..de2315c77577149150b581c7e36d0802ec9de7c9
--- /dev/null
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/ParticipantTaskAssignment.java
@@ -0,0 +1,67 @@
+package cz.muni.ics.kypo.training.adaptive.domain;
+
+import cz.muni.ics.kypo.training.adaptive.domain.phase.AbstractPhase;
+import cz.muni.ics.kypo.training.adaptive.domain.phase.Task;
+import cz.muni.ics.kypo.training.adaptive.domain.training.TrainingRun;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+@Entity
+@Table(name = "participant_task_assignment")
+public class ParticipantTaskAssignment implements Serializable {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "participantTaskAssignmentGenerator")
+    @SequenceGenerator(name = "participantTaskAssignmentGenerator", sequenceName = "participant_task_assignment_seq")
+    @Column(name = "participant_task_assignment_id", nullable = false, unique = true)
+    private Long id;
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "phase_id")
+    private AbstractPhase abstractPhase;
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "task_id")
+    private Task task;
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "training_run_id")
+    private TrainingRun trainingRun;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public AbstractPhase getAbstractPhase() {
+        return abstractPhase;
+    }
+
+    public void setAbstractPhase(AbstractPhase abstractPhase) {
+        this.abstractPhase = abstractPhase;
+    }
+
+    public Task getTask() {
+        return task;
+    }
+
+    public void setTask(Task task) {
+        this.task = task;
+    }
+
+    public TrainingRun getTrainingRun() {
+        return trainingRun;
+    }
+
+    public void setTrainingRun(TrainingRun trainingRun) {
+        this.trainingRun = trainingRun;
+    }
+
+    @Override
+    public String toString() {
+        return "ParticipantTaskAssignment{" +
+                "id=" + id +
+                '}';
+    }
+}
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/facade/TrainingRunFacade.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/facade/TrainingRunFacade.java
index cc0439fbcde2203cc74daf9a8a1070c96ac1337a..aea7b536efc7b23905c686f49a6e50c7a61dc79f 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/facade/TrainingRunFacade.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/facade/TrainingRunFacade.java
@@ -265,8 +265,7 @@ public class TrainingRunFacade {
             "or @securityService.isTraineeOfGivenTrainingRun(#trainingRunId)")
     @TransactionalWO
     public AbstractPhaseDTO getNextPhase(Long trainingRunId) {
-        AbstractPhase abstractPhase;
-        abstractPhase = trainingRunService.getNextPhase(trainingRunId);
+        AbstractPhase abstractPhase = trainingRunService.getNextPhase(trainingRunId);
         return getCorrectAbstractPhaseDTO(abstractPhase);
     }
 
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/ParticipantTaskAssignmentRepository.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/ParticipantTaskAssignmentRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a4453e0745a147af6cece99367833fc69a1dba3
--- /dev/null
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/ParticipantTaskAssignmentRepository.java
@@ -0,0 +1,11 @@
+package cz.muni.ics.kypo.training.adaptive.repository;
+
+import cz.muni.ics.kypo.training.adaptive.domain.ParticipantTaskAssignment;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.querydsl.QuerydslPredicateExecutor;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ParticipantTaskAssignmentRepository extends JpaRepository<ParticipantTaskAssignment, Long>, QuerydslPredicateExecutor<ParticipantTaskAssignment> {
+    //TODO provide a SQL commands that returns all the relations between task transitions
+}
\ No newline at end of file
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingRunService.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingRunService.java
index fd8908fd2a289e08e90addb305fa80af730f1632..c89e7e7acb0960fb856e9417a5d7742dfd1e5edd 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingRunService.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingRunService.java
@@ -2,6 +2,7 @@ package cz.muni.ics.kypo.training.adaptive.service.training;
 
 import com.querydsl.core.types.Predicate;
 import cz.muni.ics.kypo.training.adaptive.annotations.transactions.TransactionalWO;
+import cz.muni.ics.kypo.training.adaptive.domain.ParticipantTaskAssignment;
 import cz.muni.ics.kypo.training.adaptive.domain.TRAcquisitionLock;
 import cz.muni.ics.kypo.training.adaptive.domain.User;
 import cz.muni.ics.kypo.training.adaptive.domain.phase.*;
@@ -10,6 +11,7 @@ import cz.muni.ics.kypo.training.adaptive.domain.training.TrainingInstance;
 import cz.muni.ics.kypo.training.adaptive.domain.training.TrainingRun;
 import cz.muni.ics.kypo.training.adaptive.enums.TRState;
 import cz.muni.ics.kypo.training.adaptive.exceptions.*;
+import cz.muni.ics.kypo.training.adaptive.repository.ParticipantTaskAssignmentRepository;
 import cz.muni.ics.kypo.training.adaptive.repository.TRAcquisitionLockRepository;
 import cz.muni.ics.kypo.training.adaptive.repository.UserRefRepository;
 import cz.muni.ics.kypo.training.adaptive.repository.phases.AbstractPhaseRepository;
@@ -51,6 +53,7 @@ public class TrainingRunService {
     private final ElasticsearchServiceApi elasticsearchServiceApi;
     private final UserManagementServiceApi userManagementServiceApi;
     private final TRAcquisitionLockRepository trAcquisitionLockRepository;
+    private final ParticipantTaskAssignmentRepository participantTaskAssignmentRepository;
 
     /**
      * Instantiates a new Training run service.
@@ -72,7 +75,8 @@ public class TrainingRunService {
                               AuditEventsService auditEventsService,
                               ElasticsearchServiceApi elasticsearchServiceApi,
                               UserManagementServiceApi userManagementServiceApi,
-                              TRAcquisitionLockRepository trAcquisitionLockRepository) {
+                              TRAcquisitionLockRepository trAcquisitionLockRepository,
+                              ParticipantTaskAssignmentRepository participantTaskAssignmentRepository) {
         this.sandboxServiceApi = sandboxServiceApi;
         this.trainingRunRepository = trainingRunRepository;
         this.abstractPhaseRepository = abstractPhaseRepository;
@@ -82,6 +86,7 @@ public class TrainingRunService {
         this.elasticsearchServiceApi = elasticsearchServiceApi;
         this.userManagementServiceApi = userManagementServiceApi;
         this.trAcquisitionLockRepository = trAcquisitionLockRepository;
+        this.participantTaskAssignmentRepository = participantTaskAssignmentRepository;
     }
 
     /**
@@ -201,11 +206,20 @@ public class TrainingRunService {
         trainingRun.setCurrentPhase(nextPhase);
         trainingRun.setIncorrectAnswerCount(0);
         trainingRunRepository.save(trainingRun);
+        participantTaskAssignmentRepository.save(prepareDataForSankeyGraph(trainingRun, nextPhase));
         auditEventsService.auditPhaseStartedAction(trainingRun);
 
         return nextPhase;
     }
 
+    private ParticipantTaskAssignment prepareDataForSankeyGraph(TrainingRun trainingRun, AbstractPhase nextPhase) {
+        ParticipantTaskAssignment participantTaskAssignment = new ParticipantTaskAssignment();
+        participantTaskAssignment.setTrainingRun(trainingRun);
+        participantTaskAssignment.setAbstractPhase(nextPhase);
+        participantTaskAssignment.setTask(trainingRun.getCurrentTask());
+        return participantTaskAssignment;
+    }
+
     /**
      * Finds all Training Runs of specific Training Definition of logged in user.
      *
diff --git a/src/main/resources/db/migration/V1__db_adaptive_trainings_schema.sql b/src/main/resources/db/migration/V1__db_adaptive_trainings_schema.sql
index 154f5e9113f8f84bd863e60a2f1982a21d37e1f9..cf0506f50cf9d5f01e3fee58b138987909113a30 100644
--- a/src/main/resources/db/migration/V1__db_adaptive_trainings_schema.sql
+++ b/src/main/resources/db/migration/V1__db_adaptive_trainings_schema.sql
@@ -5,6 +5,17 @@ create table "user" (
     primary key (user_id)
 );
 
+create table participant_task_assignment (
+    participant_task_assignment_id bigserial not null,
+    phase_id int8 not null,
+    training_run_id int8 not null,
+    task_id int8,
+    primary key (participant_task_assignment_id),
+    foreign key (phase_id) references abstract_phase,
+    foreign key (training_run_id) references training_run,
+    foreign key (task_id) references task,
+);
+
 -- TRAINING
 create table training_definition (
     training_definition_id bigserial not null,
diff --git a/src/main/resources/db/migration/V2__db_adaptive_trainings_sequences.sql b/src/main/resources/db/migration/V2__db_adaptive_trainings_sequences.sql
index d38dd26a0b02004792e2992aceaf7b85973d02be..710040a894f8244e5d16249549c06e562b5fb5a6 100644
--- a/src/main/resources/db/migration/V2__db_adaptive_trainings_sequences.sql
+++ b/src/main/resources/db/migration/V2__db_adaptive_trainings_sequences.sql
@@ -12,3 +12,4 @@ CREATE SEQUENCE training_run_seq AS bigint INCREMENT 50 MINVALUE 1;
 CREATE SEQUENCE access_token_seq AS bigint INCREMENT 50 MINVALUE 1;
 CREATE SEQUENCE tr_acquisition_lock_seq AS bigint INCREMENT 50 MINVALUE 1;
 CREATE SEQUENCE user_seq AS bigint INCREMENT 50 MINVALUE 1;
+CREATE SEQUENCE participant_task_assignment_seq AS bigint INCREMENT 50 MINVALUE 1;