2016-01-13 10 views
5

Jestem refactoring Zend Framework aplikacji do używania doktryny 2.5 DBAL zamiast Zend_DB (ZF1). Mam następujące zapytanie Zend_Db:Dołącz do podkwerendy z doktryną 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); 

Skutkuje to w poniższym zapytaniu 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') 

nie mogę dowiedzieć się, jak dołączyć do podzapytania stosując doktrynę 2.5 Konstruktora kwerend. W głównym zapytaniu muszę wybrać kolumny z podzapytania.

Przeczytałem here, że doktryna nie obsługuje łączenia podkwerend. Jeśli to nadal prawda, czy mogę napisać to zapytanie w inny sposób przy użyciu kreatora zapytania SQL z doktryny DBAL? Natywny SQL może nie być dobrym rozwiązaniem dla mnie, ponieważ zapytanie to będzie dynamicznie rozszerzane później w kodzie.

+2

Pobierz wynik swojego subSelect, a następnie użyj go jako parametru wybranego. – Veve

+0

@Veve Wynik subSelektu będzie tablicą zawierającą tysiące elementów, nie sądzę, że jest to możliwe, aby go najpierw pobrać i użyć jako parametru w głównym zapytaniu. – aimfeld

+0

Czy to DQL lub SQL, który próbujesz zbudować? – Ocramius

Odpowiedz

7

Znalazłem rozwiązanie, dostosowując do tego DQL example DBAL. Sztuką jest uzyskanie surowego SQL z podzapytaniem, zawinięcie go w nawiasy i dołączenie do niego. Parametry używane w podzapytaniu muszą być ustawione w głównym zapytaniu:

+2

Myślę, że w tym wierszu jest błąd: '-> leftJoin ('us', sprintf ('(% s)', $ subSelect-> getSQL()), 'firstAccess', 'us.userSurveyID = firstAccess.userSurveyID') ' Trzecim argumentem musi być' Expr \ Join: : ON' lub 'Expr \ Join :: WITH. – Tsounabe

+1

' Expr \ Join :: ON' i 'Expr \ Join :: WITH' stosuje się tylko do zapytania" ORM "QueryBuilder. na przykład '\ Doctrine \ ORM \ Query \ Expr \ Join' do użytku z' \ Doctrine \ ORM \ QueryBuilder :: join' Autonomiczny 'DBAL' nie ma obiektu' Join'. Łączenia 'DBAL' są domyślnie zawsze warunkowe. Zobacz: 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

nie działa, patrz https://stackoverflow.com/questions/24600439/error-in-nested-subquery-in-dql-class-is-not- określone –

3

Aby odpowiedzieć na tę część zapytanie:

nie mogę dowiedzieć się, jak dołączyć do podzapytania stosując doktrynę 2,5 Query Builder

Można dokonać instancji konstruktora 2 kwerendy i korzystanie DQL z drugiego w klauzuli pierwszego zapytania. Przykład:

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

Sprawdź przykłady here lub here lub find more using Google

+0

Może to działać dla podzapytań w klauzuli where, ale muszę wybierz kolumny w głównym zapytaniu z podzapytania. – aimfeld

+0

@aimfeld możesz to zrobić (odwołując się do głównego zapytania) ustawiając 'u1' i' u2', a następnie wykonaj 'andWhere ('u1.id = u2.id');'. – Wilt

+0

Zaktualizowałem opis końcowym zapytaniem mysql.Byłoby bardzo pomocne, gdybyś mógł podać przykład kodu, aby osiągnąć to zapytanie (nie rozumiem, co masz na myśli, przepraszam). – aimfeld