13

我正在编写一个 CakePHP 1.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 的有序列表。但是那里有重复项。

在 Cookbook 中四处挖掘,我找到了一个使用 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 字段,但无法摆脱它。

谢谢你,弗兰克·卢克

4

12 回答 12

24

尝试使用'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'));
于 2009-11-20T07:48:14.833 回答
19

你是对的,看来你不能使用DISTINCTwith list。由于您不需要id但只需要名称,因此您可以find all像上面那样使用 then $first_names = Set::extract($first_names, '/Person/first_name');。这将为您提供一个具有不同名字的数组。

于 2009-11-11T22:45:45.317 回答
5

你可以试试这个。这里以 Person id 作为键,所以没有重复条目的机会。

    $first_names = $this->Person->find('list', array(
    'fields' => array('id','first_name'),
    'conditions' => array('Person.status' => '1'),
   ));
    $this->set('first_names', $first_names);
于 2014-01-23T07:43:19.057 回答
4

以下是我在 CakePHP 3.x 中的做法:

     $query = $this->MyTables->find('all');
     $result = $query->distinct()->toArray();
于 2015-08-27T11:52:45.057 回答
3

使用 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);
于 2013-06-19T20:43:48.427 回答
3

我知道这是 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查询要强大一些。

如果您只想区分一个字段的结果,因此只需丢弃具有重复名称的行,您还可以使用 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

希望我能为 CakePHP 3 提供一些帮助。:)

于 2015-06-04T18:21:44.770 回答
2

是的,问题是您正在使用为 id / value 输出设计的列表。您可能必须执行 find('all') 然后自己构建列表。

于 2009-11-11T22:46:10.977 回答
2

是的,我也尝试使用“列表”获取独特的结果,但它不起作用。然后我通过使用“全部”解决了这个问题。

于 2009-11-12T06:19:18.020 回答
2

本书第 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')
    ));
    // ...
}

使用上面的代码示例,生成的 var 看起来像这样:

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

)

您必须以稍微不同的方式规划查询,并规划数据库以适应列表查找。

于 2013-04-12T12:25:27.227 回答
2

在某些情况下,您希望使用某个键进行分组,但您希望结果中有唯一元素。例如,您有一个包含两种类型事件的日历应用程序。一个事件发生在第 1 天,另一个事件发生在第 1 个月的第二天。您想要显示或统计所有事件,按日期和类型分组。如果你只使用DISTINCT,那是相当困难的。最简单的解决方案是分组两次:

$this->Events->virtualFields['count'] = 'COUNT(*)';                   
$acts  = $this->Activity->find('all',array(                   
             'group' => array('DAY(Event.start)','EventType.id'),
               ));
于 2014-04-03T15:10:39.820 回答
1

只需按您想要区分的字段进行分组..或使用Set::extract()然后array_unique()

于 2013-12-03T06:37:16.590 回答
1

在 2.7-RC 版本中,这是有效的

$this->Model1->find('list', array(
      'fields' => array('Model1.field1', Model1.field1')
));
于 2015-07-04T14:44:49.537 回答