mysql FOUND_ROWS() return wrong value - php

I'm trying to use FOUND_ROWS() in my query, but the function returns wrong values sometimes.
SELECT SQL_CALC_FOUND_ROWS adminslog.*, admins.fullName FROM adminslog
JOIN admins ON admins.id=adminslog.userId ORDER BY date DESC LIMIT 0,12
In this query, I get the right value for some, but in others the limit has the wrong value.
LIMIT 0,12 164rows right
LIMIT 12,12 164rows right
LIMIT 36,12 164rows right
LIMIT 48,12 164rows right
LIMIT 50,12 60rows wrong
LIMIT 62,12 60rows wrong
Here is my class construct:
class list_table
{
public $number,$page_number,$all_rec,$table_rows,$query_str,$query,$fetch,$table,$db,$fields,$i=0,$page_n,$onclick;
function __construct($query_str,$fields,$page_n,$onclick,$page_number,$number,$db)
{
$this->fields = $fields; $this->page_number = (((int)$page_number<1)?1:(int)$page_number); $this->number = (int)$number; $this->db = $db;
$this->i = $this->page_number*$this->number-$this->number; $this->page_n = $page_n; $this->onclick = $onclick;
$this->query_str = substr(trim($query_str),0,7)."SQL_CALC_FOUND_ROWS ".substr(trim($query_str),7)." LIMIT ".(($this->page_number*$this->number)-$this->number).",".$this->number;
$this->query = $this->db->query($this->query_str);
$this->table_rows = $this->db->query("SELECT FOUND_ROWS()")->fetchColumn();
$this->all_rec = $this->query->rowCount();
$this->fetch = $this->query->fetch();
//$this->table_rows = $this->table_rows->fetch();
//$this->table_rows = $this->table_rows['cnt'];
print $this->table_rows;
}
other functions...
}

A mysql bug can be responsible for this issue, depending on which version you use:
http://bugs.mysql.com/bug.php?id=1468
You can workaround it by using a GROUP BY clause in your query.

question: you think your first FOUND_ROWS() is right every time in every query?
check that,if that is true you can run this code only in first query and save it to session.
if($this->page_number==1) $_SESSION['cr'] = $this->table_rows = $this->db->query("SELECT FOUND_ROWS()")->fetchColumn();
in this way you have not to check row counts every time.

Related

How to count returned rows [duplicate]

I am using count function to get the number of rows buffered in a resultset.
But it always returns count as one even if resultset is empty.
Please see the code below:
$dbhandle = new SQLite3("sqlitedb_111.db");
$selQuery1 = "SELECT id,dbname,tabname,fieldname FROM scan_results ORDER BY id ASC LIMIT 0,10";
$resQuery1 = $dbhandle->query($selQuery1);
print count($resQuery1);
What am I doing wrong and how can I fix this?
As per your comment if you just want to return the count of records you could wrap your query in a SELECT COUNT(*) and change $dbhandle->query to $dbhandle->querySingle. This will work with or without LIMIT.
$dbhandle = new SQLite3("sqlitedb_111.db");
$selQuery1 = "SELECT COUNT(*) FROM (SELECT id,dbname,tabname,fieldname FROM scan_results ORDER BY id ASC LIMIT 0,10)";
$resQuery1 = $dbhandle->querySingle($selQuery1);
print count($resQuery1);
Result is an array. find the size of the array.
$dbhandle = new SQLite3("sqlitedb_111.db");
$selQuery1 = "SELECT id,dbname,tabname,fieldname FROM scan_results ORDER BY id ASC LIMIT 0,10";
$resQuery1 = $dbhandle->query($selQuery1);
$noofrows=sizeof($resQuery1);
echo $noofrows;
SQLite is an embedded database, i.e., there is no client/server communication overhead.
Therefore, it can return the results dynamically; there is only a single row buffered at any time.
To get the number of result rows, you either have to step through the results, or execute something like SELECT COUNT(*) FROM (original query).
Call numRows() on the result set.
From http://php.net/manual/en/function.sqlite-num-rows.php
<?php
$db = new SQLiteDatabase('mysqlitedb');
$result = $db->query("SELECT * FROM mytable WHERE name='John Doe'");
$rows = $result->numRows();
echo "Number of rows: $rows";
?>

Count number of rows buffered in sqlite result set

I am using count function to get the number of rows buffered in a resultset.
But it always returns count as one even if resultset is empty.
Please see the code below:
$dbhandle = new SQLite3("sqlitedb_111.db");
$selQuery1 = "SELECT id,dbname,tabname,fieldname FROM scan_results ORDER BY id ASC LIMIT 0,10";
$resQuery1 = $dbhandle->query($selQuery1);
print count($resQuery1);
What am I doing wrong and how can I fix this?
As per your comment if you just want to return the count of records you could wrap your query in a SELECT COUNT(*) and change $dbhandle->query to $dbhandle->querySingle. This will work with or without LIMIT.
$dbhandle = new SQLite3("sqlitedb_111.db");
$selQuery1 = "SELECT COUNT(*) FROM (SELECT id,dbname,tabname,fieldname FROM scan_results ORDER BY id ASC LIMIT 0,10)";
$resQuery1 = $dbhandle->querySingle($selQuery1);
print count($resQuery1);
Result is an array. find the size of the array.
$dbhandle = new SQLite3("sqlitedb_111.db");
$selQuery1 = "SELECT id,dbname,tabname,fieldname FROM scan_results ORDER BY id ASC LIMIT 0,10";
$resQuery1 = $dbhandle->query($selQuery1);
$noofrows=sizeof($resQuery1);
echo $noofrows;
SQLite is an embedded database, i.e., there is no client/server communication overhead.
Therefore, it can return the results dynamically; there is only a single row buffered at any time.
To get the number of result rows, you either have to step through the results, or execute something like SELECT COUNT(*) FROM (original query).
Call numRows() on the result set.
From http://php.net/manual/en/function.sqlite-num-rows.php
<?php
$db = new SQLiteDatabase('mysqlitedb');
$result = $db->query("SELECT * FROM mytable WHERE name='John Doe'");
$rows = $result->numRows();
echo "Number of rows: $rows";
?>

Does mysql_fetch_array reset the query var?

For example I have a mysql query that gets some data. Then runs another query based some of the data that it got.
If i just return the first query, in my case $qOne. Everything works great.
BUT, after using my while loop while ($row = mysql_fetch_array($qOne)) It then returns as an empty array. (but the second query I return DOES work)
I tried to see if I could "save" the first query in another var im not messing with like this $savedResult = $qOne, then i'd just return the $savedResult but that did not work.
Does anyone know how I can get my function below to return both of the results? Thanks!
function getFoods($sort, $start, $limit) {
$qOne = mysql_query("SELECT a.id, a.name, a.type, AVG(b.r) AS fra, COUNT(b.id) as tvotes FROM `foods` a LEFT JOIN `foods_ratings` b ON a.id = b.id GROUP BY a.id ORDER BY fra DESC, tvotes DESC LIMIT $start, $limit;");
$i = 0;
$qry = "";
while ($row = mysql_fetch_array($qOne)) {
$fid = $row['id'];
if ($i > 0)
$qry .= " UNION ";
$i++;
$qry .= "SELECT fid, ing, amount FROM foods_ing WHERE fid='$fid'";
}
$qTwo = mysql_query($qry);
return array($qOne, $qTwo);
}
When you have returned the two query result resources, remember that you will need to fetch from them when you actually want to use them. (we don't see the code where you implement that).
To make use of $qOne after you already have looped through it, you must rewind it back to the first position. That is done with mysql_data_seek()
mysql_data_seek($qOne, 0);

Order results by count of that row

I'm trying to make a function which will display the top X results of the row Y which I set, for this instance I'm using the row browser and the top 5 results from my table statistics, the where is just to eliminate Search Bot results from showing up. I also want it to return the count of the amount of rows as well. So say there was 10 results for the browser 'Safari', then it would return the count of 10 for that result as well as the result itself.
$display->show_list('statistics', 'browser', '5', 'WHERE browser!=\'Search Bot\'');
Here is my function. I'm cleaned it up a bit to remove certain checks and outputs if the query were to fail, etc.
function show_list($table, $row, $limit = 5, $where = NULL) {
$item = mysql_query("SELECT DISTINCT $row FROM $table $where LIMIT $limit");
$result = array();
while ($fetch = mysql_fetch_array($item)) {
$result[] = $fetch;
}
return $result;
}
Not sure I understand the question, but what about using a group by clause, in your SQL query :
select your_column, count(*)
from your_table
where ...
group by your_column
order by count(*) desc
limit 5
That would get you :
for each value of your_column,
the number of rows with that value
and you'd keep the 5 values of your_column that have the biggest number of rows
Change this line:
$item = mysql_query("SELECT $row, count(*) as rows FROM $table $where GROUP BY count(*) ORDER BY count(*) DESC LIMIT $limit");
After doing that, you may not want to mix this with your generic show_list function.
A random note. DISTINCT tends to be somewhat expensive on the database. I would avoid defaulting to doing it.
Incidentally your indentation is..interesting. No decent programmer will want to work with that code without reformatting to some consistent indentation scheme. There are endless arguments about the best way to format, but the following would be a reasonable indentation of your original code:
function show_list($table, $row, $limit = 5, $where = NULL) {
$item = mysql_query("SELECT DISTINCT $row FROM $table $where LIMIT $limit");
$result = array();
while ($fetch = mysql_fetch_array($item)) {
$result[] = $fetch;
}
return $result;
}
function show_list($table, $column, $limit = 5, $where = '') {
$item = mysql_query("SELECT $column, COUNT(*) AS c FROM $table $where
GROUP BY $column ORDER BY c LIMIT $limit");
$result = array();
while ($fetch = mysql_fetch_array($item)) {
$result[] = $fetch;
}
return $result;
}
Replace row with column - we are actually passing a column name in the variable.
Replace $where = null with $where = '' - it will ensure that the query works correctly even when $where is null.
Modify the query to generate the expected results (to the best of my understanding of your question)
Re-format the code and indent it properly.

Zend Framework Select Objects And UNION()

I'm pretty sure this is not possible in Zend Framework (I have searched the Web, the documentation and issue tracker) but I just want to make sure so I'm asking here.
$select = $this->select();
$select->union($select1, $select2);
That doesn't work of course. To explain what I need. I need to use UNION() to merge 2 tables in a SELECT query, I know I could just do:
$select = "$select1 UNION $select2";
The problem is that would return a string and I need to get a select object so I can use it with Zend_Paginator.
I have already solved the issue by modifying my database architecture but I'm just curious if there is some workaround for this.
Here's what I've done to make a union:
$select = $this->select();
//common select from both sides of the union goes here
$select1 = clone($select);
//select1 specifics here
$select2 = clone($select);
//select 2 specifics here
$db = $this->getAdapter();
$pageselect = $db->select()->union(array("($select1)", "($select2)"));
Remember Db_Select's __toString will print out the SQL generated by that select, to help you debug.
Zend_Db_Select has a union method so I'd have thought it is possible, if you can build your query using a select object. I haven't used Zend_Db_Select (or the table subclass) with union but I'd imagine you can do something like
$select = $this->select()
->where('blah')
->union($sql);
a complete example:
public function getReservationById($id)
{
if(!$id) return null;
$sql = $this->table->select();
$sql->union(array(
$this->table->select()->where('id=?', $id),
$this->tableFinished->select()->where('id=?', $id),
$this->tableCanceled->select()->where('id=?', $id),
$this->tableTrashed->select()->where('id=?', $id)
));
echo $sql->__toString();
}
and the generated query:
SELECT reservations.* FROM reservations WHERE (id='5658') UNION SELECT res_finished.* FROM res_finished WHERE (id='5658') UNION SELECT res_cancel.* FROM res_cancel WHERE (id='5658') UNION SELECT res_trash.* FROM res_trash WHERE (id='5658')
This practical example shows a function that returns a rowset of either latest or if a available favourite blog entries of a specific year (artwork blog):
public function fetchBestOf($year)
{
$selectLatest = $this->select()->where('isHidden = 0')
->where('YEAR(dateCreated) = ' . $year)
->where('isHighlight = 0');
$selectHighlights = $this->select()->where('isHidden = 0')
->where('YEAR(dateCreated) = ' . $year)
->where('isHighlight = 1');
$selectUnion = $this->select()->union(array($selectLatest, $selectHighlights), Zend_Db_Select::SQL_UNION_ALL)
->order('isHighlight DESC')
->order('dateCreated DESC')
->order('workID DESC')
->limit('5');
$rowset = $this->fetchAll($selectUnion);
return $rowset;
}
The best way Zend suggest is like follows....
$sql = $this->_db->select()
->union(array($select1, $select2,$select3))
->order('by_someorder');
echo $sql->__toString();
$stmt = $db->query($sql);
$result = $stmt->fetchAll();
echo will show the query
Here $select1, $select2, $select3 can be different select queries with same
number of columns...
This is how it works for me:
$select1 = $this->select();
$select2 = $this->select();
After getting the necessary data in both queries the UNION syntax goes like this:
$select = $this->select()->union(array('('.$select1.')', '('.$select2.')'));

Categories