I'm trying to use an object to count the number of records in my db that meet certain criteria but I can't work out how to make it work. The following code is my count method inside my db connection class:
//Counts the total number of records and returns integer
public function totalCount($fieldname, $tablename, $where = "")
{
$q = "SELECT count(".$fieldname.") FROM "
. $tablename . " " . $where;
$result = $this->mysqli->query($q);
$count = 0;
if ($result) {
while ($row = mysqli_fetch_array($result)) {
$count = $row[0];
}
}
return $count;
}
This code is outside the class:
//New instantiation
$mydb = new myDBC();
//Count the number of transactions for the user...
$count = $mydb->totalCount('amount','transactions','WHERE userid = 13');
//output the number of transactions for the user
print $count;
For some reason this always displays 0, even though my db has thousands of records inside it that should be counted. Grateful for any pointers as to where my syntax isn't right.
Thanks
Does this method returns zero for all tables/fields or you tested only
$mydb->totalCount('amount','transactions','WHERE userid = 13');?
The count counts only NOT NULL values. To count all records pass asterisk to the count function: count(*)
Query execution returning false and it's not going inside if conditions thats why count is always zero
You can use prepared statement to prepare the query and then execute it. And, I don't think that it is essential to pass a field as argument to COUNT.
Anyway, as per your question, this would make a better query.
$q = 'SELECT COUNT( * ) FROM ' . $strTable . ' WHERE ' . $strCond;
Again, since you are using MySQLi, use prepared statements.
Related
So, I have following php query:
for($i = 0; $i < sizeof($cat_result) ; ++$i) {
$query_p = "SELECT * FROM $table WHERE id = %d";
$results[] = $wpdb->get_row($wpdb->prepare($query_p, $cat_result[$i]));
}
The search relies on $cat_result which contains numerous numbers.
For example, let say $cat_result contains the following number: '1,3,5,21,35`
Using these 5 numbers, the query will look for the db info.
However, there are scenarios where some number (for example, "21") do not exist in the db.
Then, I get PHP NOTICE: trying to get property of non-object.
How do I write "if" statement so that if the id (in this case "21") does not exist, then it simply ignores the query? (It is hard to explain what I mean by "ignore". I still want the query to do the search but if it does not find what it is looking for, then simply ignore the error).
I think you should restructure your query. That way, as long as your data is sanitized (to prevent injection as im not sure if it comes from the user or not), you can just do the following:
$cat_result = implode(",", $cat_result);
$query_p = "SELECT * FROM $table WHERE id in ( $cat_result )";
$rslt = $wpdb->get_results($query_p);
// loop result
That way, it will fetch you all in that list.
Try this:
for($i = 0; $i < sizeof($cat_result) ; ++$i) {
$query_p = "SELECT * FROM $table WHERE id = %d";
$row = $wpdb->get_row($wpdb->prepare($query_p, $cat_result[$i]));
if ($row) {
$results[] = $row;
}
}
I don't know WordPress, but I suspect get_row returns false when there are no more rows of results. Your code was putting false into $results when that happened, and later code was then trying to use that as an object.
For an application I'm trying to count the total of friends. I want to do this with a function but it isn't returning anything. It tells me this:
Warning: mysqli_query() expects at least 2 parameters, 1 given
But I only need one parameter. I think I'm totally wrong.
This is the function:
public function GetTotalOfFriends($user_id){
$db = new Db();
$select = "SELECT COUNT FROM friendship WHERE (friendship_recipient_id ='" . $user_id ."' OR friendship_applicant_id = '" . $user_id . "') AND friendship_status = 'accepted'";
$result = $db->conn->query($select);
$row = mysqli_query($result);
$total = $row[0];
echo $total;
I'm trying to print it out in this way:
$friend = new Friendship;
$numberoffriends = $friend->GetTotalOfFriends($user_id);
<?php echo $numberoffriends; ?>
You are mixing up a couple of things. The line $result = $db->conn->query($select); already seems to execute a query, but then you try to bypass your database wrapper by passing that query result again to mysqli_query.
Apart from that, I think your query itself is also wrong. COUNT needs a parameter, indicating a field or value to count. Quite often COUNT(*) is used, but COUNT('x') might be more efficient in some cases. You can also use a specific field name, and COUNT will count the non-null values for you.
The result you got is a mysql_result object, which you need to use to get to the actual data of the query result.
The documentation of this object is here and I suggest that you read it thoroughly.
One possible way to do this is using this:
$resultArray = $result->fetch_row();
This will result in the first (and only) row of your query. It is represented as an array, with one value (since your query returns only one column). You can fetch that value like this:
return $resultArray[0];
You could also use any of the other fetch methods if you want your data in a different fashion.
If I want to count one specific row (unread) in my database, how should i proceed with this MySQL query? As of now it counts the whole table.
$result_notifications = mysql_query("select count(1) FROM bhost_notifications where taker_id='$user_info[u_id]'");
$row_notifications = mysql_fetch_array($result_notifications);
$total_notifications = $row_notifications[0];
You need to alias the column.
SELECT COUNT(1) AS count ...
Then you would call $row_followers[count]. Be aware that mysql_ functions are deprecated. Learn about prepared statements when passing variables, and use PDO or MySQLi - this article will help you decide which.
I suspect you have an un-normalized database. While that is preferable in some situations, I doubt that they are in yours. As written you cannot be sure that the query will return the row you desire. SQL does not guarantee the order of rows, unless you use an order by clause.
It seems like this question indicates more problems the some syntax issues.
Over time I have written a nice function in PHP that allows me to easily look up records but still be dynamic enough to be useful in every type of query that I perform.
Usage:
if (get("select * from table", $query_array) > 0)
{
// There is at least one row returned
$result_array = mysql_fetch_array($query_array);
.
.
.
} else {
// No rows in the set
}
Function:
function get($sql, &$array)
{
$array = "";
$q = mysql_query($sql);
if (mysql_error())
{
$ret = -1;
print "<div><font style='font-family: arial; font-size: 12px;'><font style='color: red;'>Error:</font> " . mysql_error() . "<br>SQL: #sql</font></div>";
exit(1);
} else {
$ret = mysql_num_rows($q);
if ($ret > 0)
{
$array = $q;
}
}
return $ret;
}
This also gives a formatted error message in the case that there is something wron with the query. I use this all the time because it compresses the mysql_query and mysql_num_rows together into a single command.
Following code is a mock-up of my real code. I'm getting a big performance hit when myFunction is called. myTable is no more than a few hundred rows, but calling myFunction adds ~10 seconds execution time. Is there something inherently wrong with trying to access a row of a table inside a loop already accessing that table?
<select>
<?php
$stmt = SQLout ("SELECT ID,Title FROM myTable WHERE LEFT(Title,2) = ? ORDER BY Title DESC",
array ('s', $co), array (&$id, &$co_title));
while ($stmt->fetch()) {
if (myFunction($id)) // skip this function call and save 10 seconds
echo '<option value="' . $co_title . '">' . $co_title . '</option>';
}
$stmt->close();
function myFunction ($id) {
$stmt = SQLout ("SELECT Info FROM myTable WHERE ID = ?",
array ('i', $id), array (&$info));
if ($stmt->fetch()) {
$stmt->close();
if ($info == $something)
return true;
}
return false;
}
?>
SQLout is basically:
$sqli_db->prepare($query);
$stmt->bind_param;
$stmt->execute();
$stmt->bind_result;
return $stmt;
What you're doing is sometimes called the "N+1 queries" problem. You run the first (outer) query 1 times, and it returns N rows. Then you run N subordinate queries, one for each row returned by the first query. Thus N+1 queries. It causes a lot of overhead.
This would have far better performance if you could apply the "something" condition in SQL:
$stmt = SQLout ("SELECT ID,Title FROM myTable
WHERE LEFT(Title,2) = ? AND Info = ... ORDER BY Title DESC",
array ('s', $co), array (&$id, &$co_title));
In general, it's not a good idea to run queries in a loop that depends on how many rows match the outer query. What if the outer query matches 1000000 rows? That means a million queries inside the loop will hit your database for this single PHP request.
Even if today the outer query only matches 3 rows, the fact that you've architected the code in this way means that six months from now, at some unpredictable time, there will be some search that results in a vast overhead, even if your code does not change. The number of queries is driven by the data, not the code.
Sometimes it's necessary to do what you're doing, for instance of the "something" condition is complex and can't be represented by an SQL expression. But you should try in all other cases to avoid this pattern of N+1 queries.
So, if you have a "few hundred rows" in the table, you might be calling myFunction a few hundred times, depending on how many rows are returned in the first query.
Check the number of rows that first query is returning to make sure it meets your expectations.
After that, make sure you have an index on myTable.ID.
After that, I would start looking into system/server level issues. On slower systems, say a laptop hard drive, 10 queries per second might be all you can get.
Try something like this:
$stmt = SQLout ("SELECT ID,Title, Info FROM myTable WHERE LEFT(Title,2) = ? ORDER BY Title DESC",
array ('s', $co), array (&$id, &$co_title, &$info));
while ($stmt->fetch()) {
if (myFunction($info)) // skip this function call and save 10 seconds
echo '<option value="' . $co_title . '">' . $co_title . '</option>';
}
$stmt->close();
function myFunction ($info) {
if ($info == $something)
return true;
}
return false;
}
I'm using PHP ADOdb and I can get the result set:
$result = &$db->Execute($query);
How do I get the field names from that one row and loop through it?
(I'm using access database if that matters.)
It will depend on your fetch mode - if you setFetchMode to ADODB_FETCH_NUM (probably the default) each row contains a flat array of columns. If you setFetchMode to ADODB_FETCH_ASSOC you get an associative array where you can access each value by a key. The following is taken from ADODB documentation - http://phplens.com/lens/adodb/docs-adodb.htm#ex1
$db->SetFetchMode(ADODB_FETCH_NUM);
$rs1 = $db->Execute('select * from table');
$db->SetFetchMode(ADODB_FETCH_ASSOC);
$rs2 = $db->Execute('select * from table');
print_r($rs1->fields); # shows array([0]=>'v0',[1] =>'v1')
print_r($rs2->fields); # shows array(['col1']=>'v0',['col2'] =>'v1')
To loop through a set of results:
$result = &$db->Execute($query);
foreach ($result as $row) {
print_r($row);
}
Small improvement to the solution posted by #thetaiko.
If you are ONLY needing the field names, append LIMIT 1 to the end of your select statement (as shown below). This will tell the server to send you a single row with column names, rather than sending you the entire table.
SELECT * FROM table LIMIT 1;
I'm working with a table that contains 9.1M records, so this minor change speeds up the query significantly!
This is a function I use to return a field array - I've stripped out some extra stuff that, for example, allows it to work with other DBs than MySQL.
function getFieldNames($strTable, $cn) {
$aRet = array();
# Get Field Names:
$lngCountFields = 0;
$strSQL = "SELECT * FROM $strTable LIMIT 1;";
$rs = $cn->Execute($strSQL)
or die("Error in query: \n$strSQL\n" . $cn->ErrorMsg());
if (!$rs->EOF) {
for ($i = 0; $i < $rs->FieldCount(); $i++) {
$fld = $rs->FetchField($i);
$aRet[$lngCountFields] = $fld->name;
$lngCountFields++;
}
}
$rs->Close();
$rs = null;
return $aRet;
}
Edit: just to point out that, as I say, I've stripped out some extra stuff, and the EOF check is therefore no longer necessary in the above, reduced version.
I initally tried to use MetaColumnNames, but it gave differing results in VisualPHPUnit and actual site, while running from the same server, so eventually
I ended up doing something like this:
$sql = "select column_name, column_key, column_default, data_type, table_name, table_schema from information_schema.columns";
$sql .= ' where table_name="'.$table.'" and table_schema="'.$database_name.'"';
$result = $conn->Execute($sql);
while($row = $result->fetchRow()) {
$out[] = strToUpper($row['column_name']);
}
I think it should work with mysql, mssql and postgres.
The benefit of doing it like this, is that you can get the column names, even if a query from a table returns an empty set.
If you need the Coloumn names even for empty tables or for joins about multiple tables use this:
$db->Execute("SELECT .......");
// FieldTypesArray - Reads ColoumnInfo from Result, even for Joins
$colInfo = $res->FieldTypesArray();
$colNames = array();
foreach($colInfo as $info) $colNames[] = $info->name;
The OP is asking for a list of fieldnames that would result of executing an sql statement stored in $query.
Using $result->fetchRow(), even with fetch mode set to associative, will return nothing if no records match the criteria set by $query. The $result->fields array would also be empty and would give no information for getting the fieldnames list.
Actually, we don't know what's inside the $query statement. Besides, setting limit to 1 may not compatible with all database drivers supported by PHP ADOdb.
Answer by Radon8472 is the right one, but the correct code could be:
$result = $db->Execute($query);
// FieldTypesArray - an array of ADOFieldObject Objects
// read from $result, even for empty sets or when
// using * as field list.
$colInfo = [];
if (is_subclass_of($result, 'ADORecordSet')){
foreach ($result->FieldTypesArray() as $info) {
$colInfo[] = $info->name;
}
}
I have the habit of checking the class name of $result, for as PHP ADOdb will return false if execution fails.