2009-11-11 39 views
13

我正在编写一个CakePHP 1.2应用程序。我有一份我希望用户能够在不同字段上筛选的人员列表。对于每个可过滤的字段,我有一个下拉列表。选择过滤器组合,单击过滤器,页面只显示匹配的记录。在CakePHP查找函数中使用DISTINCT

在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语句。我不需要这个领域,但不能摆脱它。

谢谢 弗兰克卢克

回答

19

你说的没错,看来你不能用list使用DISTINCT。既然你不需要id但只有名字,你可以使用find all像上面那样然后$first_names = Set::extract($first_names, '/Person/first_name');。这会给你一个具有不同名字的数组。

+0

不仅没有这项工作非常的名单,但我已经在其他地方使用的命令集也。感谢您分享这个功能强大的图书馆! – 2009-11-20 17:14:45

+0

我试过了,但我仍然在结果列表中找到重复项。 – paullb 2012-06-28 03:06:22

+2

@paullb你可以使用['array_unique'](http://php.net/manual/en/function.array-unique.php)从提取的数组中删除重复项。当你在这个时候,看一下['Hash'类](http://book.cakephp.org/2.0/en/core-utility-libraries/hash.html)(自CakePHP 2.2以来)将最终取代['Set'](http://book.cakephp.org/2.0/en/core-utility-libraries/set.html)。 – 2012-07-03 05:15:47

2

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

2

是的我也尝试用'列表'获取唯一的结果,但它不工作。然后我通过使用'all'来解决这个问题。

22

尝试“按组”来使用,它的工作原理perfectry:

$first_names = $this->Person->find('list', array(
    'fields'=>'first_name', 
    'order'=>'Person.first_name ASC', 
    'conditions'=> array('Person.status'=>'1'), 
    'group' => 'first_name')); 
+1

这有效,但有意想不到的结果是按first_name排序列表,这可能不合意。 – paullb 2012-06-28 03:13:48

+0

@paullb我也有这个问题。订单问题是否有解决方案? – trante 2012-08-27 21:18:04

2

在该示例现在在book for version 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', 
    ) 

) 

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

2

使用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); 
1

只是由你想要区分的字段组合。或使用Set::extract()然后array_unique()

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); 
2

在某些情况下,您希望通过使用某个键进行分组,但您希望在结果中使用唯一元素。 例如,您有一个包含两种类型事件的日历应用程序。第一天的一个事件,第一个月的第二天的另一个事件。并且您想要显示或者说明所有的事件,按日期和按类型分组。 如果仅使用DISTINCT,则很难。最简单的解决方案是组两次:

$this->Events->virtualFields['count'] = 'COUNT(*)';     
$acts = $this->Activity->find('all',array(     
      'group' => array('DAY(Event.start)','EventType.id'), 
       )); 
2

我知道这是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方法不仅仅是插入有点强盛查询中的。

如果你想在一个字段只是不同的结果,所以刚扔掉一个名称重复的行,你也可以用不同的方法与字段的数组作为参数:

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

1

在2.7 RC版,这是工作

$this->Model1->find('list', array(
     'fields' => array('Model1.field1', Model1.field1') 
)); 
2

这里是我做到了在CakePHP中3.X:

 $query = $this->MyTables->find('all'); 
    $result = $query->distinct()->toArray();