phpmysqlcodeigniteractiverecorddistinct

CodeIgniter's distinct() method with a column as a parameter doesn't work as expected


I have a table with this structure:

opinion_id, author_id, title, content

I would like to get all the latest records from the table, one record for author, that means the latest record for every author.

My distinct function does not seem to be working.

function getOpinions() {
    $data = array();
    $this->db->select('*');
    $this->db->from('opinions');
    $this->db->join('authors', 'opinions.author_id = authors.author_id');
    $this->db->order_by('date', 'desc');
    $this->db->distinct('author_id');

    $Q = $this->db->get();
    if ($Q->num_rows() > 0) {
        foreach($Q->result_array() as $row) {
            $data[] = $row;
        }
    }
    $Q->free_result();
    return $data;
}

Solution

  • In Codeigniter, distinct does not work the way you expect it by field name. If you look at the manual - there is no argument for distinct. If you look at the code, it only takes a boolean, which defaults to true. It just adds the DISTINCT keyword to the query after the SELECT keyword. That's it.

    In your case, I think it would be better to use a GROUP BY as in $this->db->group_by('opinions.author_id');

    Hopefully the order by would work as per your need in this instance by ordering before the grouping.

    Cheers!

    EDIT - update after OP comments

    I know the ordering can be messed up - I sort of mentioned it :) Anyway, I might be assuming some of your table structure here, but this would force the GROUP BY to pick the rows on the top. I assume that the date is on the opinions table and you only want the latest row from that with author details.

    SELECT * FROM `authors`
    JOIN (
        SELECT * FROM opinions
        ORDER BY `date` DESC
    ) AS ops ON ops.author_id = authors.author_id
    GROUP BY ops.author_id
    

    You will not be able to construct this query on active record though. Hope this helps.