codeigniter select distinct function not working - php

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;
}

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.

Related

select the row with most recent date in table formed by using join and group by

i am joining three tables and applying group by to pick a single distinct row of each type. when i join with table marketing_follow i have multiple entries and to pick one i am using group by . now i want to pick the entry with most recent date in follow up table . i've been tryn to get this done for quite some time now and really need some help
public function getRegionWiseUserDetails($array){
$this->db->select('mg.region_name, mu.contact_person, mu.contact_number, mu.status, mu.company_name, mu.user_type, mf.follow_up_date, mf.date, mu.user_id');
$this->db->from('marketing_users as mu');
$this->db->join('marketing_group as mg','mg.id = mu.region_id','left');
$this->db->join('marketing_follow_up as mf','mf.user_id_fk =
mu.user_id','left');
foreach($array as $condition){
$this->db->or_where('mg.id',$condition);
}
$this->db->order_by('mf.follow_up_date','asc');
$this->db->group_by('mf.user_id_fk');
$query = $this->db->get();
return $query->result_array();
}
You need to sort the date field in desc order. Also for asc we dont have to pass it as second paramter it defaults accept asc
$this->db->order_by('mf.follow_up_date','desc');

DQL: only last entry from a customer

I am writing a query in DQL where I want to select the latest order from a customer. Currently I only managed to get all the orders and get them based on their date in a descending order. Which means I need to filter it to go per user as well as just pick their latest entry. However , my knowledge of DQL and queries in general isn't that high I am stuck. Any help on how to continue my query would be appreciated.
public function getLatestOrder($customer){
// get the latest order from a customer
$em = $this->getEntityManager();
$q1 = $em->getRepository('AppBundle:Order')->createQueryBuilder('o')
->leftjoin("AppBundle:User", "u")
->where("u.id = :customer_user_id")
->setParameter('customer_user_id', $customer)
->orderBy('o.date', 'DESC' );
$q1 = $q1->getQuery();
$res1 = $q1->getResult();
return $res1;
}
Additional info: The order entity has a customer column which refers to the user info.
Instead of join better you can use sub queries.
You can try this:
$em->getRepository('AppBundle:Order')->createQueryBuilder('o')
->leftjoin("AppBundle:User", "u")
->leftjoin("AppBundle:Order", "laterOrder", 'WITH', 'laterOrder.date > o.date')
->where("u.id = :customer_user_id")
->andWhere("laterOrder is null")

Symfony 2 Multiple Selects with counts on the same table?

Ok I have a flag field on one table, open or closed which is boolean. I am trying to build one query that would take that field and count them based on that flag. Then I will need to group them by account ID
Here is what I am working with now,
$GetTest1 = $GetRepo->createQueryBuilder('s') <- I had 'w' in here but all that did was add an index and not a second alias?
->select(' (count(s.open_close)) AS ClosedCount, (count(w.open_close)) AS OpenCount ')
->where('s.open_close = ?1')
//->andWhere('w.open_close = ?2')
->groupBy('s.AccountID')
->setParameter('1', true)
//->setParameter('2', false)
->getQuery();
Is what I want do-able? I know (or at lest think) that I can build a query with multiple table alias? - Please correct me if I am wrong.
All help most welcome.
Thanks
This DQL query will group the rows in table by accountId and for each of them it will give you count for yes (and you can get count for no by substracting that from total).
BTW I found writing straight DQL queries much more straightforward than writing QueryBuilder queries (which i use only when i need to dynamically construct the query)
$results = $this->get("doctrine")->getManager()
->createQuery("
SELECT t.accountId, SUM(t.openClose) as count_yes, COUNT(t.accountId) as total
FROM AppBundle:Table t
GROUP BY t.accountId
")
->getResult();
foreach ($results as $result) {
//echo print_r($result);
//you can get count_no as $result["total"] - $result["count_yes"];
}

Result from two tables order by date

can you help I have two tables images and note. I would like to get all items from these tables and order by date. It is possible I am using active record in codeigniter. Tables are independent.
Thank you for replies.
this should work:
$this->db->orderby("date", "ASC"); //or desc
$query = $this->db->get('images'); //or $query = $this->db->get('note');
$result=$query->result_array();
print_r($result);
or if you want use union all
$this->db->query('SELECT * FROM (SELECT id, date FROM images UNION ALL SELECT id, date FROM note) result ORDER BY result.date');
Notice that each SELECT statement within the UNION must have the same number of columns. The columns must also have similar data types. Also, the columns in each SELECT statement must be in the same order from http://www.w3schools.com/sql/sql_union.asp.
I think you want a Cross Join.
Here is your codeigniter code
$this->db->from("images ,note");
$this->db->select("images.*,note.*);
//make sure both dont have same column name other wise use this
//$this->db->select("images.column1,images.column2,note.column1);
$this->db->orderby("images.date", "DESC");
//you can add more orderby
//you can add where condition too
$result=$this->db->get()->result_array();
Now you will get the cross product.
Hope it will help you.
In which table do you have date column? I assume you have it in images table.
$this->db->select('images.coulmn1, images.culmn2, images.date_col, note.col1, note.col2');
$this->db->from('images');
$this->db->join('note', 'note.key1 = images.key1); //key1 is key field to relate both table.
$this->db->order_by("images.date_col", "desc");
$result = $this->db->get()->result_array();
Hope it will help.
Try this:
$this->db->select('*');
$this->db->from('images');
$this->db->join('note');
$this->db->orderby("date column name", "ASC");
$query = $this->db->get();
$result=$query->result_array();
print_r($result);

Random record from mysql database with CodeIgniter

I researched over the internet, but could not find anything...
I have a mysql db, and records at a table, and I need to get random record from this table at every page load. how can I do that? Is there any func for that?
Appreciate! thanks
SORTED:
link: http://www.derekallard.com/blog/post/ordering-database-results-by-random-in-codeigniter/
$this->db->select('name');
$query = $this->db->get('table');
$shuffled_query = $query->result_array();
shuffle ($shuffled_query);
foreach ($shuffled_query as $row) {
echo $row['name'] . '<br />';
}
Codeigniter provides the ability to order your results by 'RANDOM' when you run a query. For instance
function get_random_page()
{
$this->db->order_by('id', 'RANDOM');
or
$this->db->order_by('rand()');
$this->db->limit(1);
$query = $this->db->get('pages');
return $query->result_array();
}
I've used this before and found it to work fine.
I don't know about codeigniter, but getting a random dataset is
SELECT * FROM table ORDER BY RAND() LIMIT 1
The relevant part is "ORDER BY RAND()", obviously.
Do you know how many records there are in the table? You could do something like this:
$count=mysql_exec('select count(*)-1 from some_table');
$count=rand(1,$count);
then:
select * from
some_Table
limit $count,1
This code snippet worked well for me.
$this->db->select('name');
$this->db->order_by('rand()');
$this->db->limit(1);
$query = $this->db->get('<table>'); //<table> is the db table name
return $query->result_array();
Getting random record from large table is very expensive.
Don't use ORDER BY RAND().
This is a bad idea, but if you have a small table no problem.
In a huge databases this type of queries very slow.
I use codeigniter with datamapper. This is the code which I use to get a record randomly from table Advertiser:
$ad = new Advertiser();
$ad->limit(3);
$ad->order_by('id', 'RANDOM');
$ad->get();
SELECT product_id, title, description
FROM products
WHERE active = 1
AND stock > 0
ORDER BY RAND()
LIMIT 4
The ORDER BY RAND() clause returns random records! You can limit records also using LIMIT.
Lets think we have table where we deleted some rows. There is maybe ID not continues correctly. For sample id: 1,5,24,28,29,30,31,32,33 (9 rows)
mysql_num_rows returns 9
Another methods will return not existing rows:
$count=9; //because mysql_num_rows()==9
$count=rand(1,$count); // returns 4 for sample, but we havn't row with id=4
But with my method you always get existing rows. You can separate code and use first 2 code anywhere on site.
// Inside of Controller Class
function _getReal($id,$name_of_table)
{
$Q=$this->db->where('id',$id)->get($name_of_table);
if($Q->num_rows()>0){return $Q;}else{return FALSE;}
}
function _getLastRecord($name_of_table)
{
$Q=$this->db->select("id")->order_by('id DESC')->limit("1")->get($name_of_table)->row_array();
return $Q['id'];
}
function getrandom()
{
$name_of_table="news";
$id=rand(1,$this->_getLastRecord($name_of_table));
if($this->_getReal($id,$name_of_table)!==FALSE)
{
echo $id;
// Here goes your code
}
else
{
$this->getrandom();
}
// END
Getting random record from large table is very expensive. But bellow this code is very effective ..
$count=mysql_num_rows(mysql_query("select * from table_name WHERE SOME_OF_YOUR_CONDITION"));
$nums=rand(1,$count);
mysql_query(" select * from table_name WHERE SOME_OF_YOUR_CONDITION LIMIT $count,1");
This will be helpful ...
I think this is not best way. For sample, you've deleted record which is now==$count. You must iterate this for mysql_num_rows()
This function retrieve all rows in table in random order
public function get_questions(){
$this->db->select('*');
$this->db->order_by('rand()');
$this->db->from('multiple_choices');
$query = $this->db->get();
return $query->result_array();
}
Random row without ORDER BY RAND() query:
$all_rows = $this->db->get('table')->result_array();
$random_row = $all_rows[rand(0,count($all_rows)-1)];

Categories