protected static function prepare_export_query(array $contextids, $userid) {
        global $DB;

        $makefetchsql = function($istmp) use ($DB, $contextids, $userid) {
            $ctxfields = context_helper::get_preload_record_columns_sql('ctx');
            list($insql, $inparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED);

            $i = $istmp ? 0 : 1;
            $istmpsqlval = $istmp ? 1 : 0;
            $prefix = $istmp ? 'idtmp' : 'id';
            $uniqid = $DB->sql_concat("'$prefix'", 'fc.id');

            $sql = "
                SELECT $uniqid AS uniqid,
                       f.id AS feedbackid,
                       ctx.id AS contextid,

                       $istmpsqlval AS istmp,
                       fc.id AS submissionid,
                       fc.anonymous_response AS anonymousresponse,
                       fc.timemodified AS timemodified,

                       fv.id AS valueid,
                       fv.course_id AS valuecourse_id,
                       fv.item AS valueitem,
                       fv.completed AS valuecompleted,
                       fv.tmp_completed AS valuetmp_completed,

                       $ctxfields
                  FROM {context} ctx
                  JOIN {course_modules} cm
                    ON cm.id = ctx.instanceid
                  JOIN {feedback} f
                    ON f.id = cm.instance
                  JOIN {%s} fc
                    ON fc.feedback = f.id
                  JOIN {%s} fv
                    ON fv.completed = fc.id
                 WHERE ctx.id $insql
                   AND fc.userid = :userid{$i}";

            $params = array_merge($inparams, [
                'userid' . $i => $userid,
            ]);

            $completedtbl = $istmp ? 'feedback_completedtmp' : 'feedback_completed';
            $valuetbl = $istmp ? 'feedback_valuetmp' : 'feedback_value';
            return [sprintf($sql, $completedtbl, $valuetbl), $params];
        };

        list($nontmpsql, $nontmpparams) = $makefetchsql(false);
        list($tmpsql, $tmpparams) = $makefetchsql(true);

        // Oracle does not support UNION on text fields, therefore we must get the itemdescription
        // and valuevalue after doing the union by joining on the result.
        $sql = "
            SELECT q.*,

                   COALESCE(fv.value, fvt.value) AS valuevalue,

                   fi.id AS itemid,
                   fi.feedback AS itemfeedback,
                   fi.template AS itemtemplate,
                   fi.name AS itemname,
                   fi.label AS itemlabel,
                   fi.presentation AS itempresentation,
                   fi.typ AS itemtyp,
                   fi.hasvalue AS itemhasvalue,
                   fi.position AS itemposition,
                   fi.required AS itemrequired,
                   fi.dependitem AS itemdependitem,
                   fi.dependvalue AS itemdependvalue,
                   fi.options AS itemoptions

              FROM ($nontmpsql UNION $tmpsql) q
         LEFT JOIN {feedback_value} fv
                ON fv.id = q.valueid AND q.istmp = 0
         LEFT JOIN {feedback_valuetmp} fvt
                ON fvt.id = q.valueid AND q.istmp = 1
              JOIN {feedback_item} fi
                ON (fi.id = fv.item OR fi.id = fvt.item)
          ORDER BY q.contextid, q.istmp, q.submissionid, q.valueid";
        $params = array_merge($nontmpparams, $tmpparams);

        return [$sql, $params];
    }