2013-01-20 16 views
6

Próba znalezienia zagnieżdżonego zaznaczenia przy użyciu Zend\Db\Sql\Select i nie może nic zobaczyć w dokumentacji lub w google.Zagnieżdżanie Wybierz za pomocą ZF2

Chcąc zrobić coś takiego:

SELECT 
    table1.*, 
    (SELECT x,y,z FROM table2 WHERE table2.a = table1.a) as b 
FROM table1 

Bez czegoś zagnieżdżonych select, by to wyglądać tak:

$select = new Zend\Db\Sql\Select; 
$select 
->columns(array(
    '*' 
)) 
->from('table1') 

ZF1 wyglądała o tworzeniu elementu podselekcji a następnie dodanie go jako Wyrażenie wewnątrz listy kolumn, ale w ZF2 narzeka na wyrażenie, które musi być łańcuchem.

Edytuj: Wybór zagnieżdżony musi być kolumną, ponieważ kończę pomnożonymi wierszami podczas korzystania z GROUP BY na tej samej nazwie kolumny. Jest to prawidłowe zapytanie Próbuję dostać się Zend\Db\Sql\Select:

SELECT 
    users.id, 
    (SELECT count(explorations.id) FROM explorations WHERE user_id = users.id) as total_explorations, 
    count(villages.id) 
FROM 
    users 
INNER JOIN 
    villages 
     on (villages.user_id = users.id) 
GROUP BY 
    users.id 

Odpowiedz

4

Proponuję, aby zrestrukturyzować zapytanie SQL. Nie jestem pewien, której bazy danych używasz, ale jeśli używasz MySQL, funkcja COUNT może używać słowa kluczowego DISTINCT. W ten sposób nie liczą się zduplikowane identyfikatory. Poprawiłem twoje zapytanie SQL do tego, co bym użył, w ten sposób wyeliminujesz potrzebę wewnętrznego wyboru.

SELECT 
    users.id, 
    COUNT(DISTINCT explorations.id) AS total_explorations, 
    COUNT(DISTINCT villages.id) AS total_villages 
FROM users 
    INNER JOIN villages ON villages.user_id = users.id 
    INNER JOIN explorations ON explorations.user_id = users.id 
GROUP BY users.id 

Nie uruchomiłem tego zapytania, ale jestem pewien, że powinien zadziałać i dać pożądany wynik. Mam nadzieję, że nie pomylę się z twoją sytuacją. Poniżej znajduje się odpowiednik Zend Framework 2 select.

$select = $sql->select('users'); 
$select->columns(array('id')); 
$select->join('villages', 
       'villages.user_id = users.id', 
       array(
        'total_villages' => new Expression("COUNT(DISTINCT villages.id)") 
       ) 
); 
$select->join('explorations', 
       'explorations.user_id = users.id', 
       array(
        'total_explorations' => new Expression("COUNT(DISTINCT explorations.id)") 
       ) 
); 
0

Mam nadzieję, że jestem coraz problem poprawnie ...

Nadal nie zmodernizowane się do ZF2 ale jest to jeden sposób, w jaki może utworzyć zagnieżdżoną instrukcję Select w ZF1, jeśli używasz architektury MVC (spróbuj również w ZF2).

$table1 = new table1(); 
    $table1->select()->from('table1',array('*', 
     'b' => '(SELECT x,y,z FROM table2 WHERE table2.a = table1.a)', 
    )); 

Aktualizacja:

Wróciłem do tego po komentarzu i zorientował się, że kod Pisałem nie będzie działać, ponieważ nie będą mogli zaznaczyć kilka kolumn z innej tabeli w jednej kolumnie (tj. x, y, z w b).

Ale tak, to by działało, gdybyś musiał wykonać trochę ag. funkcja na drugiej tabeli, która podaje pojedynczą kolumnę. na przykład

$table1 = new table1(); 
    $table1->select()->from('table1',array('*', 
     'b' => '(count (*) FROM table2 WHERE table2.a = table1.a)', 
    )); 

To by zadziałało. W ten sposób można uzyskać niektóre z kolumn z wykonywaniem niektórych funkcji. A pozostałe kolumny z drugiej tabeli (tabela 2) można uzyskać za pomocą sprzężenia.

+0

To jest obecnie to, do czego wróciłem, ponieważ nie byłem w stanie tego zrobić. Właśnie napisałem SQL na surowo, jak powiedziałeś, ale potem połowa jest wyodrębniana, a druga połowa jest surowa: D Myślałem, że ZF2 po prostu pozwoli na to w sekcji kolumn –

0

To, co opisujesz, jest zdefiniowane jako JOIN. Istnieje kilka różnych scenariuszy łączenia i nie będę omawiał ich różnicy, ale najbardziej wspólne to INNER JOIN lub LEFT JOIN.

I to jest rzeczywiście można znaleźć wewnątrz ZF2-Documentation of Zend\Db\Sql#Join

Query będzie wyglądać następująco:

Select 
    t1.*, 
    t2.field1, 
    t2.field2, 
    t2.field3 
FROM 
    tablename1 t1, 
    tablename2 t2 
WHERE 
    t1.field = t2.field 

Patrząc Dokumentacji ZF2-Documentation of Zend\Db\Sql#Join, ja myśleć Select będzie wyglądać następująco:

$select = new \Zend\Db\Sql\Select(); 

$select->columns(array(
    'id', 
    'title', 
    // List ALL Columns from TABLE 1 - * is bad/slow! 
), true)->from(array(
    't1' => 'tablename1' 
))->join(
    'tablename2', 
    'id = t1.id', 
    array(
     'username', 
     'email', 
     // List ALL Columns from TABLE 2 u want to select 
    ), 
    $select::JOIN_INNER 
) 

Kolejny Myślę, że: Jeśli nie użyjesz columns(), to zrób to sam, zacznij pisać dobre pytania;) Miej większą kontrolę nad swoim kodem!

Nie mogę obiecać, że ten kod działa, ponieważ nie używam Zend \ Db na własną rękę, ale korzystanie z Dokumentacji we właściwym miejscu powinno jednak spowodować, że będziesz działać.

+0

Mmm, używam również innych złączeń i nie mogę zrobić innego, ponieważ mnoży wiersze, ponieważ używam wielu count() i sum(). Grupuję według określonego pola, ale jest to również używane w połączonym stole, więc nie sądzę, że istnieje inny sposób obejścia go poza tym, że ma się wybór zagnieżdżony. –

6

Ralph Schindler ma repozytorium różnych wzorców DB, które specjalnie zaimplementował w Zend \ Db. Oto jeden za obsługę żądań: https://github.com/ralphschindler/Zend_Db-Examples/blob/master/example-20.php

Zawartość jest taka:

<?php 

/** @var $adapter Zend\Db\Adapter\Adapter */ 
$adapter = include ((file_exists('bootstrap.php')) ? 'bootstrap.php' : 'bootstrap.dist.php'); 
refresh_data($adapter); 

use Zend\Db\Sql; 
use Zend\Db\ResultSet\ResultSet; 

$sql = new Sql\Sql($adapter); 

$subselect = $sql->select(); 
$subselect->from('artist') 
    ->columns(array('name')) 
    ->join('album', 'artist.id = album.artist_id', array()) 
    ->where->greaterThan('release_date', '2005-01-01'); 


$select = $sql->select(); 
$select->from('artist') 
    ->order(array('name' => Sql\Select::ORDER_ASCENDING)) 
    ->where 
     ->like('name', 'L%') 
     ->AND->in('name', $subselect); 

$statement = $sql->prepareStatementForSqlObject($select); 

$result = $statement->execute(); 

$rows = array_values(iterator_to_array($result)); 

assert_example_works(
    count($rows) == 2 
    && $rows[0]['name'] == 'Lady Gaga' 
    && $rows[1]['name'] == 'Linkin Park' 
); 

Zasadniczo, można użyć jednego wybierz jako wartość predykatu innego wybierz.

+0

Czy można wykonać SubSelect jako dodatkową kolumnę bez wykonywania innego połączenia DB? Dostaję pomnożone wiersze, jeśli mam więcej niż 1 licznik, więc wybierz podrzędny, aby ominąć to. Wysłałem przykładowy kod SQL w oryginalnym pytaniu, aby pokazać, o co mi chodzi :) –