Присоединить подзапрос с доктриной 2 DBAL

Я рефакторинг приложения Zend Framework 2 для использования доктрины 2.5 DBAL вместо Zend_DB (ZF1). У меня есть следующий запрос Zend_Db:

$subSelect = $db->select() ->from('user_survey_status_entries', array('userSurveyID', 'timestamp' => 'MIN(timestamp)')) ->where('status = ?', UserSurveyStatus::ACCESSED) ->group('userSurveyID'); $select = $db->select() // $selectColNames contains columns both from the main query and // the subquery (eg firstAccess.timestamp AS dateFirstAccess). ->from(array('us' => 'user_surveys'), $selectColNames) ->joinLeft(array('firstAccess' => $subSelect), 'us.userSurveyID = firstAccess.userSurveyID', array()) ->where('us.surveyID = ?', $surveyID); 

Это приводит к следующему запросу MySQL:

 SELECT `us`.`userSurveyID`, // More columns from main query `us` `firstAccess`.`timestamp` AS `dateFirstAccess` FROM `user_surveys` AS `us` LEFT JOIN ( SELECT `user_survey_status_entries`.`userSurveyID`, MIN(timestamp) AS `timestamp` FROM `user_survey_status_entries` WHERE (status = 20) GROUP BY `userSurveyID` ) AS `firstAccess` ON us.userSurveyID = firstAccess.userSurveyID WHERE (us.surveyID = '10') 

Я не могу понять, как присоединиться к подзапросу, используя построитель запросов doctrine 2.5. В основном запросе мне нужно выбрать столбцы из подзапроса.

Я читал здесь, что доктрина не поддерживает объединение подзапросов. Если это все еще так, могу ли я написать этот запрос по-другому, используя построитель SQL-запросов доктрины DBAL? Собственный SQL не может быть хорошим решением для меня, так как этот запрос будет динамически расширяться позже в коде.

Я нашел решение, адаптировав этот пример DQL к DBAL. Хитрость заключается в том, чтобы получить необработанный SQL подзапроса, обернуть его в скобки и присоединиться к нему. Параметры, используемые в подзапросе, должны быть заданы в основном запросе:

 $subSelect = $connection->createQueryBuilder() ->select(array('userSurveyID', 'MIN(timestamp) timestamp')) ->from('user_survey_status_entries') // Instead of setting the parameter in the main query below, it could be quoted here: // ->where('status = ' . $connection->quote(UserSurveyStatus::ACCESSED)) ->where('status = :status') ->groupBy('userSurveyID'); $select = $connection->createQueryBuilder() ->select($selectColNames) ->from('user_surveys', 'us') // Get raw subquery SQL and wrap in brackets. ->leftJoin('us', sprintf('(%s)', $subSelect->getSQL()), 'firstAccess', 'us.userSurveyID = firstAccess.userSurveyID') // Parameter used in subquery must be set in main query. ->setParameter('status', UserSurveyStatus::ACCESSED) ->where('us.surveyID = :surveyID')->setParameter('surveyID', $surveyID); 

Чтобы ответить на эту часть вашего вопроса:

Я не могу понять, как присоединиться к подзапросу, используя построитель запросов doctrine 2.5

Вы можете создать два экземпляра построителя запросов и использовать DQL из второго внутри предложения первого запроса. Пример:

 ->where($qb->expr()->notIn('u.id', $qb2->getDQL()) 

Проверьте примеры здесь или здесь или найдите больше, используя Google