2016-01-13 15 views
5

Ich Refactoring ein Zend Framework Anwendung Lehre Doktrin 2.5 DBAL anstelle von Zend_DB (ZF1) zu verwenden. Ich habe folgende Zend_Db query:Beitreten Unterabfrage mit Doktrin 2 DBAL

$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); 

Daraus ergibt sich die folgende MySQL-Abfrage:

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') 

Ich kann nicht herausfinden, wie die Unterabfrage zu verbinden, die Lehre 2.5 Query Builder verwenden. In der Hauptabfrage muss ich Spalten aus der Unterabfrage auswählen.

Ich habe here gelesen, dass Doktrin Unterabfragen zu verbinden nicht unterstützt. Wenn das immer noch richtig ist, kann ich diese Abfrage auf andere Weise schreiben, indem ich den SQL-Abfrage-Generator von Doktrin DBAL verwende? Native SQL ist möglicherweise keine gute Lösung für mich, da diese Abfrage später im Code dynamisch erweitert wird.

+2

Rufen Sie das Ergebnis Ihrer subSelect ab und verwenden Sie es als Parameter Ihrer Auswahl. – Veve

+0

@Veve das Ergebnis der subSelect wird ein Array mit Tausenden von Elementen sein, ich glaube nicht, es ist praktikabel, es zuerst abzurufen und es als Parameter in der Hauptabfrage zu verwenden. – aimfeld

+0

Ist diese DQL oder SQL, die Sie versuchen zu erstellen? – Ocramius

Antwort

7

Ich habe eine Lösung gefunden, indem Sie diese DQL example zu DBAL anzupassen. Der Trick besteht darin, das rohe SQL der Unterabfrage zu erhalten, in Klammern zu schreiben und es zu verbinden. Die in der Unterabfrage verwendeten Parameter müssen in der Hauptabfrage eingestellt sein:

$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); 
+2

Ich glaube, in dieser Zeile ist ein Fehler: '-> leftJoin ('us', sprintf ('(% s)', $ subSelect-> getSQL()), 'firstAccess', 'us.userSurveyID = firstAccess.userSurveyID') ' Das dritte Argument muss' Expr \ Join lauten: : ON' oder 'Expr \ Join :: WITH'. – Tsounabe

+1

' Expr \ Join :: ON' und 'Expr \ Join :: WITH' gelten nur für den' Namespace 'ORM' QueryBuilder. z.B. '\ Doctrine \ ORM \ Query \ Expr \ Join' zur Verwendung mit' \ Doctrine \ ORM \ QueryBuilder :: join' Das eigenständige 'DBAL' hat kein' Join'-Objekt. Die 'DBAL'-Joins sind implizit immer ein 'ON'-Zustand. Siehe: http://www.doctrine-project.org/api/dbal/2.5/class-Doctrine.DBAL.Query.QueryBuilder.html#_join vs http://www.doctrine-project.org/api/orm/ 2.5/class-Doctrine.ORM.QueryBuilder.html # _join – fyrye

+0

funktioniert nicht, ref auf https://stackoverflow.com/questions/24600439/error-in-nested-subquery-in-dql-class-is-not- definiert –

3

Um diesen Teil Ihrer Frage zu beantworten:

ich nicht herausfinden kann, wie die Unterabfrage zu verbinden, die Lehre 2.5 Query Builder mit

Sie 2 Query Builder-Instanzen machen und zu verwenden die DQL von der zweiten in einer Klausel Ihrer ersten Abfrage. Ein Beispiel:

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

prüfen Beispiele here oder here oder find more using Google

+0

Dies funktioniert möglicherweise für Unterabfragen in der Where-Klausel, aber ich muss Wählen Sie Spalten in der Hauptabfrage aus der Unterabfrage aus. – aimfeld

+0

@aimfeld können Sie das tun (binden Sie an Ihre Hauptabfrage), indem Sie 'u1' und' u2' setzen und dann 'andWhere ('u1.id = u2.id');'. – Wilt

+0

Ich habe die Beschreibung mit der letzten mysql-Abfrage aktualisiert.Es wäre sehr hilfreich, wenn Sie ein Codebeispiel geben könnten, um diese Abfrage zu erreichen (ich verstehe nicht, was Sie meinen, tut mir leid). – aimfeld

Verwandte Themen