使用doctrine 2 DBAL加入子查询

aim*_*eld 8 php mysql query-builder doctrine-orm zend-framework2

我正在重构Zend Framework 2应用程序以使用doctrine 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);
Run Code Online (Sandbox Code Playgroud)

这导致以下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')
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚如何使用doctrine 2.5查询构建器加入子查询.在主查询中,我需要从子查询中选择列.

我在这里读过,学说不支持加入子查询.如果仍然如此,我可以使用doctrine DBAL的SQL查询构建器以另一种方式编写此查询吗?本机SQL对我来说可能不是一个好的解决方案,因为此查询将在代码中稍后动态扩展.

aim*_*eld 14

我通过调整这个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);
Run Code Online (Sandbox Code Playgroud)

  • 不起作用,请参阅 /sf/ask/1722030761/ (3认同)
  • 不起作用,您将在“JOIN(SELECT”附近得到[语义错误]第0行,第174列:错误:此处不支持子查询 (3认同)
  • 我认为这一行有一个错误:` - > leftJoin('us',sprintf('(%s)',$ subSelect-> getSQL()),'firstAccess','us.userSurveyID = firstAccess.userSurveyID' )`第三个参数必须是`Expr\Join :: ON`或`Expr\Join :: WITH .... (2认同)
  • 它确实有效,但请仔细阅读作者的所有建议,包括代码中的注释 (2认同)
  • 所有列名、表名都需要是原始sql,而不是实体名称或字段名称。另请注意,使用 $connection->createQueryBuilder() 而不是 $em->>createQueryBuilder() (2认同)

Wil*_*ilt 6

要回答您问题的这一部分:

我不知道如何使用 2.5 查询构建器加入子查询

您可以创建 2 个查询构建器实例,并在第一个查询的子句中使用第二个中的 DQL。一个例子:

->where($qb->expr()->notIn('u.id', $qb2->getDQL())
Run Code Online (Sandbox Code Playgroud)

检查的例子在这里在这里找到更多使用谷歌