Count rows before adding a further limit statement CodeIgniter? - php

I have ran into a problem...
I have a bunch of where statments like so...
$this->db->where('Pool', "1");
$this->db->where('Bedrooms >=', "3");
Then a limit statement
$this->db->limit($limit, $offset);
And finally my get statement
$query = $this->db->get('table-name');
My problem is I need to count the results before my limit statement, to get the total rows without the limit.. So I tried this..
$this->db->where('Pool', "1");
$this->db->where('Bedrooms >=', "3");
$num_rows = $this->db->count_all_results();
$this->db->limit($limit, $offset);
$query = $this->db->get('table-name');
This counts my rows with the where statements fine.. However, the get statement now gets records without the previous where statements working.
It's not visible, but there is a large amount of code handling more where statements, and grabbing things in urls, So I'd prefer not to perform the retrieval of data twice in order to fix this...
Cheers!

I know this is an old question, but I just ran into this problem and came up with a different solution.
The idea is to take a copy of the db class before the limit and offset.
$this->db->where('Pool', "1");
$this->db->where('Bedrooms >=', "3");
//here we use the clone command to create a shallow copy of the object
$tempdb = clone $this->db;
//now we run the count method on this copy
$num_rows = $tempdb->from('table-name')->count_all_results();
$this->db->limit($limit, $offset);
$query = $this->db->get('table-name');

I know that's an old question but I found a pretty simple solution.
//do your select, from and where
$this->db->select('your selects');
$this->db->from('your table');
$this->db->where('your where');
//get the filtered rows count
//the trick is the first empty parameter and second false parameter
$filtered_count = $this->db->count_all_results('', false);
//limit your results and get the rows
$this->db->limit($length, $start);
$results = $this->db->get()->result_array();
Hope it helps someone

$get_data = $this->your_model->get_data();
$data = $get_data['data'];
$count = $get_data['count'];
Model
function get_data($limit = 10, $offset= 0)
{
$table = 'table-name';
$where = array('Pool' => 1, 'Beedrooms >=' 3);
$return['data'] = $this->db->from($table)->where($where)->limit($limit, $offset)->get();
$return['count'] = $this->db->from($table)->where($where)->count_all_results();
return $return;
}

$this->db->select('*');
$this->db->from('users');
$this->db->where('active',$status);
//open1 here we copy $this->db in to tempdb and apply
//count_all_results() function on to this tempdb
$tempdb = clone $this->db;
$num_results= $tempdb->count_all_results();
// now applying limit and will get actual result
$this->db->limit(10);
$this->db->get();
$query = $this->db->last_query();
$res = $this->db->query($query);
$data_array = array('num_results' => $num_results, 'results' => $res->result() );
return $data_array;

It is quite evident that you would need to use two different queries. It would be optimum to do this as quickly as possible using a single query, but since you need to get all the records before the second query, we need to use two queries.
However, you can optimize the first query based on the engine you use with MySQL. If you use InnoDB then you should use SELECT COUNT(*) FROM <table-name> cause the total row size is cached in InnoDB.
I believe count_all_rows uses count(*) for performance and you should be sorted using this direcctly.
With MyISAM you can use COUNT(<column-name>).
So, you have a count function in your model class which returns the count for your table and then you can call the function to insert/update/get data from your database.

You can use SQL_CALC_FOUND_ROWS of mysql
SELECT SQL_CALC_FOUND_ROWS * FROM table1
WHERE
cond1, cond2, ..., condN
LIMIT 10
SELECT FOUND_ROWS();
This is using mysql, you may need to check how to use it codeignitor way.
Reference:
https://dev.mysql.com/doc/refman/5.7/en/information-functions.html#function_found-rows

I know this question is old but I had the same issue and got a simpler solution than the displayed here. No need to build the query twice and no need to clone the db class. Just count the result without resting the query builder after you add the where part and then you add the limit and execute your query.
$this->db->where('Pool', 1);
$this->db->where('Beedrooms >=' 3);
$count = $this->db->count_all_results('table-name', false); // No reset query builder
$this->db->limit($limit, $offset)
$result = $this->db->get();
You are going to have two variables:
$count with the number of results and $result with the result.

Related

CodeIgniter: How to get the number of records before get all results?

I need to get the number of records for a query before apply a limit. I tried with the following code:
$db = $this->load->database();
$this->db->select($this->select_column)
->from($this->table);
echo $this->db->count_all_results();
But count_all_results don't return any number. If I excecute $this->db->get(), I obtained a result sets, but first I need to apply a limit.
What can be happenning with $this->db->count_all_results()?
Is there another solution for get the count of rows returned based on the previews query?
I'm using Codeigniter 3 with MySQL.
Try doing the the following first to get the count:
$this->db->select('count(*) as ct');
$count = $this->db->get($this->table)->result()[0]->ct;
Now your variable $count has the count you need to apply the limit, so you can
$this->db->.... // Your code
$this->load->database(); // Database is lodaed
$query = $this->db->get('table_name');
return $query->num_rows();
// This will return count of total rows
//After that you can return the result
return $query->result();

Codeigniter newbie: Count query results?

I have my query:
$query = $this->db
->get_where('users', array('group_id' => 7, 'active' => 1));
It works if I use:
print_r ($query->result());
All I want to do, is get the total number of rows that match my query. I've tried num_rows and count(), but I can't get either of them to work!
Any help would be greatly appreciated! At the moment, I am just testing this in my view, but will move it over to my model when I figure it out.
Thanks!!
You need to use $query->num_rows(). It will return total number of rows returned using your query.
for example :
$query = $this->db->query("YOUR QUERY");
if ($query->num_rows() > 0)
{
//DO your stuff
}
For more reference see Documentation.
Try count_all_results
Example:
echo $this->db->count_all_results('my_table');
// Produces an integer, like 25
$this->db->like('title', 'match');
$this->db->from('my_table');
echo $this->db->count_all_results();
// Produces an integer, like 17
OR
echo $this->db->where('group_id',1)->count_all_results('users');

modify and redo last query in codeigniter

Can I get last query made with active record class and modify some parts of it and redo that query in codeigniter. I am trying to get total pages for my pagination. I can't directly write my query because it is dynamically created on runtime within some for loops and if statements depending on the form submitted to the page.
Do you run your query twice because of the total pages? If yes, check SQL_CALC_FOUND_ROWS and FOUND_ROWS() in SQL.
$this->db->select("SQL_CALC_FOUND_ROwS id",false);
$this->db->any_AR_function(....);
$this->db->limit(...);
$result = $this->db->get();
After this you can call this:
$this->db->select("FOUND_ROWS() as count",false);
$count = $this->db->get();
I hope this is what you want.
You can get last query using:
$last_query = $this->db->last_query();
You can modify this query and then do:
$query = $this->db->query($modified_query);
foreach($query->result() as $row)
{
}

how to "keep" codeigniter activerecord status

In my article CURD list, I need to get articles from database using many conditions, after get number of eligible articles(no limit), I need to get first 10 eligible articles (limit 10). So I want to keep the activerecord status, if it's possible, I don't need to write those 'where' again. Here are my code:
//select num
$this->db->select('count(*) as num')
//conditions
$this->db->where/or_where/having/order_by//many conditions...
//get num
$num = $this->db->get('articles')->first_row()->num;
//get articles
$this->db->limit(10);
$articles = $this->db->get('articles')->result();
When I finished my first query, the active record status is empty, so the second query is wrong. Is there any way to keep that?
I know this is old, but I was also looking for a way to do this, eventually found the built in solution:
// Start of the query you want to re-use
$this->db->start_cache();
//select num
$this->db->select('count(*) as num')
//conditions
$this->db->where/or_where/having/order_by//many conditions...
// End of the query you want to re-use
$this->db->stop_cache();
//get num
$num = $this->db->get('articles')->first_row()->num;
//get articles
$this->db->limit(10);
$articles = $this->db->get('articles')->result();
// Clear the saved query
$this->db->flush_cache();
I believe there is no reason why the approach you are taking shouldn't work. For instance taking your code snippet, tidying up and applying some conditions to it:
//select num
$this->db->select('count(*) as num');
//conditions
$this->db->where(array('title' => 'Hello world'));
//get num
$num = $this->db->get('articles')->first_row()->num;
//get articles
$this->db->limit(10);
$articles = $this->db->get('articles')->result();
echo "!".$num."!<br />";
print_r($articles);
exit();
Using this within my test application I gather the $num result and then a full recordset within $articles.
You could just use a simple if clause
function get_data($type) {
//select num
$this->db->select('count(*) as num')
//conditions
$this->db->where/or_where/having/order_by//many conditions...
//get num
if($type == 'count')
return $this->db->get('articles')->first_row()->num;
//get articles
if($type == 'articles') {
$this->db->limit(10);
return $this->db->get('articles')->result();
}
}
Although I am not sure if there is anything specific for codeigniter that can simplify this, this should work.

Codeigniter return result and row

In the Model class I use return $query->row(); to return single rows and return $query->result(); when returning multiple rows.
On a single page I have to return single rows and multiple rows from 2 separate tables.
Table users contains general information like the user name, full name, and email address.
Table user_links contains links submitted by the respective user and has multiple rows for each user.
My query
$this->db->select('*');
$this->db->from('users');
$this->db->join('user_links', "user_links.user_id = users.user_id");
$this->db->where('users.user_id', $user_id);
$this->db->where('user_links.user_id', $user_id);
$query = $this->db->get();
return $query->row();
In my controller I load the query in my view by
$data['row'] = $this->User_model->user_read($user_id);,
$user_id being the 3rd URL segment containing the unique user id.
Finally, in my view I retrieve rows by echo $row->first_name;
This works for single rows but how can I create a foreach loop for user links? The goal is to avoid loops for single rows and use them just for retrieving multiple rows.
This is psuedo code but you can probobly do something like this
$this->db->select('*');
$this->db->from('users');
$this->db->join('user_links', "user_links.user_id = users.user_id");
$this->db->where('users.user_id', $user_id);
$this->db->where('user_links.user_id', $user_id);
$query = $this->db->get();
if ($query->num_rows() == 1)
{
return $query->row();
}
elseif ($query->num_rows() > 1)
{
return $query->result_array(); //This returns an array of results which you can whatever you need with it
}
else
{
//Add some logic to handle if there are zero results
}
If I understand your question correctly, you want to get both the user data as well as user_links data with a single query while avoiding iterating through it to get the user's data. While this may be possible using result_array, I would advise against it since you will get 0 results when there are no entries in user_links for that particular user.
My suggestion is that you use two queries, one to get the user from the user table, another to get user's links from user_links table. This will also help you avoid joins.
Hard to tell what you want.
You want a function that checks if you're passing a row() or a result() and treat them accordingly.
In my opinion your code would be easier to read (and maintain) if you just passed everything as a result(). And do check if the set is empty to show a nice message to the user.
Sounds like you're looking for some of the other features already provided by CI's Active Record: http://codeigniter.com/user_guide/database/results.html
For what you are doing it sounds like using the built in function result_array would work. You use it like so:
TAKEN FROM LINK ABOVE
$query = $this->db->query("YOUR QUERY");
foreach ($query->result_array() as $row)
{
echo $row['title'];
echo $row['name'];
echo $row['body'];
}
You can just replace this line:
$this->db->join('user_links', "user_links.user_id = users.user_id");
With this one:
$this->db->join('user_links', "user_links.user_id = users.user_id", 'left outer');
Join in codeigniter uses INNER JOIN by default but in some cases if there is no data in user_links it returns nothing so u can use LEFT JOIN in your frame work CI it used like i mentioned above.

Categories