私はCakePHP1.2アプリを書いています。ユーザーがさまざまなフィールドでフィルタリングできるようにしたいユーザーのリストがあります。フィルタ可能なフィールドごとに、ドロップダウンリストがあります。フィルタの組み合わせを選択し、[フィルタ]をクリックすると、一致するレコードのみがページに表示されます。
People_controllerには、次のコードがあります。
$first_names = $this->Person->find('list', array(
'fields'=>'first_name',
'order'=>'Person.first_name ASC',
'conditions'=> array('Person.status'=>'1')
));
$this->set('first_names', $first_names);
(ソフト削除を使用しているため、ステータス= 1です。)
これにより、すべてのfirst_namesの順序付きリストが作成されます。しかし、重複はそこにあります。
クックブックを掘り下げて、DISTINCTキーワードを使用した例を見つけ、それを使用するようにコードを変更しました。
$first_names = $this->Person->find('list', array(
'fields'=>'DISTINCT first_name',
'order'=>'Person.first_name ASC',
'conditions'=> array('Person.status'=>'1')
));
これにより、次のようなSQLエラーが発生します。
Query: SELECT `Person`.`id`, DISTINCT `Person`.` first_name` FROM `people` AS `Person` WHERE `Person`.`status` = 1 ORDER BY `Person`.`first_name` ASC
問題は明らかです。フレームワークはPerson.idをクエリに追加しています。これは「リスト」の使用によるものと思われます。
フィルタボタンがクリックされたときに、選択したフィルタを使用してSQLステートメントを作成します。 isフィールドは必要ありませんが、削除することはできません。
ありがとう、フランク・ルーク
そうです、DISTINCT
をlist
と一緒に使用することはできないようです。 id
は必要なく、名前だけが必要なので、上記のように_find all
_を使用してから、$first_names = Set::extract($first_names, '/Person/first_name');
を使用できます。これにより、個別の名を持つ配列が得られます。
'group by'を使用してみてください、それは完璧に機能します:
$first_names = $this->Person->find('list', array(
'fields'=>'first_name',
'order'=>'Person.first_name ASC',
'conditions'=> array('Person.status'=>'1'),
'group' => 'first_name'));
あなたはこれを試すことができます。ここでは、個人IDをキーとして使用するため、エントリが重複する可能性はありません。
$first_names = $this->Person->find('list', array(
'fields' => array('id','first_name'),
'conditions' => array('Person.status' => '1'),
));
$this->set('first_names', $first_names);
これが私がCakePHP3.xでそれをした方法です:
$query = $this->MyTables->find('all');
$result = $query->distinct()->toArray();
SQLグループ化を使用すると、個別のリストも生成されます。マイナスの結果があるかどうかはわかりませんが、私にとってはうまくいくようです。
$first_names = $this->Person->find('list', array(
'fields' => 'first_name',
'order' => 'first_name',
'group' => 'first_name',
'conditions' => array('Person.status' => '1'),
));
$this->set('first_names', $first_names);
CakePHP 1.2の質問であることは知っていますが、CakePHPバージョン3でもそれを探していました。このバージョンには、クエリを個別のクエリに形成する方法があります。
$first_names = $this->Persons->find(
'list',
[
'fields'=> ['name']
]
)
->distinct();
;
これにより、次のようなSQLクエリが生成されます。
SELECT DISTINCT Persons.name AS `Persons__name` FROM persons Persons
ただし、distinct
メソッドは、クエリにDISTINCT
を挿入するよりも少し強力です。
1つのフィールドの結果を区別したいだけで、名前が重複している行を破棄する場合は、フィールドの配列をパラメーターとして使用して、distinctメソッドを使用することもできます。
$first_names = $this->Persons->find(
'list',
[
'fields'=> ['id', 'name'] //it also works if the field isn't in the selection
]
)
->distinct(['name']); //when you use more tables in the query, use: 'Persons.name'
;
これは一般的に次のようなSQLクエリになります(確かにそれはグループクエリです):
SELECT DISTINCT
Persons.id AS `Persons__id`, Persons.name AS `Persons__name`
FROM persons Persons
GROUP BY name #respectively Persons.name
CakePHP3のお手伝いをさせていただきます。:)
現在の例では バージョン2の本 それは次のように述べています:
public function some_function() {
// ...
$justusernames = $this->Article->User->find('list', array(
'fields' => array('User.username')
));
$usernameMap = $this->Article->User->find('list', array(
'fields' => array('User.username', 'User.first_name')
));
$usernameGroups = $this->Article->User->find('list', array(
'fields' => array('User.username', 'User.first_name', 'User.group')
));
// ...
}
上記のコード例では、結果の変数は次のようになります。
$justusernames = Array
(
//[id] => 'username',
[213] => 'AD7six',
[25] => '_psychic_',
[1] => 'PHPNut',
[2] => 'gwoo',
[400] => 'jperras',
)
$usernameMap = Array
(
//[username] => 'firstname',
['AD7six'] => 'Andy',
['_psychic_'] => 'John',
['PHPNut'] => 'Larry',
['gwoo'] => 'Gwoo',
['jperras'] => 'Joël',
)
$usernameGroups = Array
(
['User'] => Array
(
['PHPNut'] => 'Larry',
['gwoo'] => 'Gwoo',
)
['Admin'] => Array
(
['_psychic_'] => 'John',
['AD7six'] => 'Andy',
['jperras'] => 'Joël',
)
)
クエリを少し異なる方法で計画し、リスト検索に対応するようにデータベースを計画する必要があります。
はい、問題は、ID /値の出力用に設計されたリストを使用していることです。おそらく、find( 'all')を実行してから、自分でリストを作成する必要があります。
場合によっては、いくつかのキーを使用してグループ化したいが、結果内に一意の要素が必要な場合があります。たとえば、2種類のイベントを含むカレンダーアプリケーションがあるとします。 1日目の1つのイベントと、1か月目の2日目の別のイベント。そして、すべてのイベントを日ごとおよびタイプごとにグループ化して表示またはカウントしたいとします。 DISTINCT
のみを使用する場合、それは非常に困難です。最も簡単な解決策は、2回グループ化することです。
$this->Events->virtualFields['count'] = 'COUNT(*)';
$acts = $this->Activity->find('all',array(
'group' => array('DAY(Event.start)','EventType.id'),
));
はい、「list」を使用して一意の結果を取得しようとしましたが、機能しません。次に、「all」を使用して問題を修正しました。
2.7-RCバージョンでは、これは機能しています
$this->Model1->find('list', array(
'fields' => array('Model1.field1', Model1.field1')
));
区別したいフィールドでグループ化するか、Set::extract()
を使用してからarray_unique()
を使用します。