我正在重构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 (e.g. 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')
我无法弄清楚如何使用教义2.5查询生成器加入子查询。在主查询中,我需要从子查询中选择列。
我在这里已经读到,该学说不支持加入子查询。如果仍然如此,是否可以使用主义DBAL的SQL查询构建器以其他方式编写此查询?原生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);