web-dev-qa-db-ja.com

doctrine 2 DBALでサブクエリを結合します

Zend Framework2アプリケーションをリファクタリングして、Zend_DB(ZF1)の代わりにdoctrine 2.5 DBALを使用しています。次の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')

doctrine 2.5クエリビルダーを使用してサブクエリを結合する方法がわかりません。メインクエリでは、サブクエリから列を選択する必要があります。

私は here を読みましたdoctrineはサブクエリの結合をサポートしていません。それでも当てはまる場合、doctrine DBALのSQLクエリビルダーを使用して別の方法でこのクエリを記述できますか?このクエリはコードの後半で動的に拡張されるため、ネイティブSQLは私にとって良い解決策ではない可能性があります。

8
aimfeld

私はこれを 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);
14
aimfeld

質問のこの部分に答えるには:

doctrine 2.5クエリビルダーを使用してサブクエリを結合する方法がわかりません

2つのクエリビルダーインスタンスを作成し、最初のクエリの句内で2番目のインスタンスからのDQLを使用できます。例:

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

例を確認してください here または here または Googleを使用してさらに検索

4
Wilt