6

を使用してネストされた選択を取得しようとしてZend\Db\Sql\Selectいますが、ドキュメントまたはGoogleで何も表示されません。

このようなことをしたい:

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

ネストされた選択がなければ、次のようになります。

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

ZF1 は subSelect 項目を作成し、それを列のリスト内に Expression として追加することを検討しましたが、ZF2 では Expression が文字列である必要があると不平を言っています。

編集:ネストされた選択は、同じ列名でGROUP BYを使用すると行が乗算されるため、列として存在する必要があります。これは、私が取得しようとしている正しいクエリです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
4

4 に答える 4

6

Ralph Schindler は、Zend\Db に具体的に実装したさまざまな DB パターンのリポジトリを持っています。これはサブセレクト用のものです: https://github.com/ralphschindler/Zend_Db-Examples/blob/master/example-20.php

内容は次のとおりです。

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

基本的に、ある選択を別の選択の述語の値として使用できます。

于 2013-01-21T23:27:34.207 に答える
4

SQLクエリを再構築することをお勧めします。どのデータベースを使用しているかわかりませんが、MySQL を使用している場合は、COUNT 関数で DISTINCT キーワードを使用できます。この方法では、重複した ID をカウントしません。SQLクエリを私が使用するものに調整しました。これにより、内部選択の必要がなくなります。

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

私はこのクエリを実行していませんが、それが機能し、必要な結果が得られるはずです。うまくいけば、私はあなたの状況を誤解していません。以下は、同等の 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)")
               )
);
于 2013-04-24T04:33:20.240 に答える
0

あなたが説明しているものはJOINとして定義されています。いくつかの異なる結合シナリオがあり、それらの違いについては説明しませんが、最も一般的なのは INNER JOIN または LEFT JOIN です。

そして、これは実際にZF2-Documentation of Zend\Db\Sql#Join内にあります。

クエリは次のようになります。

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

ZF2-Documentation of Zend\Db\Sql#Join のドキュメントを見ると、 Select は次のようになると思います。

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

もう 1 つ考えられるのは、自分自身のために使用するのではなく、適切なクエリを書き始めることです ;) コードをより細かく制御できcolumns()ます。SELECT *

私自身は Zend\Db を使用していないため、このコードが機能するとは約束できませんが、適切な場所でドキュメントを使用すると、それでも実行できるはずです。

于 2013-01-20T09:44:02.647 に答える
0

私はあなたの問題を正しく理解していることを願っています...

まだ自分自身を ZF2 にアップグレードしていませんが、これは、MVC アーキテクチャを使用している場合に ZF1 でネストされた Select ステートメントを作成する方法の 1 つです (ZF2 でも試してください)。

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

アップデート:

あなたのコメントの後にこれに戻って、別のテーブルから複数の列を単一の列に選択できないため、私が書いたコードが機能しないことに気付きました(つまり、bのx、y、z)。

しかし、はい、いくつかの集計を実行する必要がある場合に備えて機能します。単一の列を提供する他のテーブルの関数。例えば

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

だからこれはうまくいくでしょう。このようにして、いくつかの関数が実行された列を取得できます。そして、結合を使用して取得できる他のテーブル(table2)の残りの列。

于 2013-01-20T04:14:16.137 に答える