public function execute(array $data) : QueryInterface
    {
        $data = Validator::validateData($this->table, $data, $this->user);

        // initialize query
        $query = $this->table->find('all');

        $where = $this->getWhereClause($data);
        $group = $this->getGroupByClause($data);
        $select = $this->getSelectClause($data);
        $order = [$this->table->aliasField($data['sort_by_field']) => $data['sort_by_order']];

        $joins = $this->byAssociations($data);
        // set joins and append to where and select parameters
        foreach ($joins as $name => $params) {
            $query->leftJoinWith($name);

            if (!empty($params['where'])) {
                $where = array_merge($where, $params['where']);
            }

            if (!empty($params['select'])) {
                $select = array_merge($select, $params['select']);
            }
        }

        $select = !empty($group) ? $group : $select;
        if (!empty($group)) {
            $select = $group;
            $select[static::GROUP_BY_FIELD] = $query->func()->count($group[0]);
        }

        // add query clauses
        $query->select($select)->where([$data['aggregator'] => $where])->order($order)->group($group);

        return $query;
    }