PDO Connection : row count using where clause - php

I want to count the no of rows in my database..along with where clause and AND clause..
please show me how can we do that in pdo..
these are my queries:
$stmt=$dbh->prepare("SELECT * from questions where (category_id = ?) AND (complexity_id = ?) ORDER BY RAND()");
$stmt->execute(array($_POST['category'],$_POST['complexity']));
$data = $stmt->fetchAll(PDO::FETCH_OBJ)
count:
$nRows = $dbh->query("SELECT COUNT(*) FROM questions");
i need to write both queries in one query only..

you can use fetchColumn.
$number_of_rows=$stmt->fetchColumn(); // will give no. of rows
$data = $stmt->fetchAll(PDO::FETCH_ASSOC)// give the data array

If your queries are different
If your queries are different, like it shown in the question, then keep them as two separate queries. There is no way to get them in one. Just leave it two separate queries, it's all right.
If your queries actually the same
If your queries actually the same, and you want to get your data filtered and also get the number of rows, then you don't need the second query at all. In PHP, there is a function called count(). You can use it to count results returned by your first query.
$nRows = count($data);
as simple as that

Can you just use
$stmt=$dbh->prepare("SELECT COUNT(*) from questions where (category_id = ?) AND (complexity_id = ?)");
query?

Related

How can I count entries in mySQL database faster?

I am counting the entries in my SQL database:
$sql = "SELECT * FROM files WHERE id = ?";
$q = $pdo->prepare($sql);
$q->execute([$id]);
$rowCount =$q->rowCount();
The result of $rowCount is 500000.
But to output this single number takes 5 seconds! Is it possible to get this result faster?
Use the COUNT() function https://dev.mysql.com/doc/refman/8.0/en/counting-rows.html:
$sql = "SELECT COUNT(*) FROM files WHERE id = ?";
Also ensure that 'id' is an indexed column:
https://dev.mysql.com/doc/refman/8.0/en/mysql-indexes.html
Replace * with a field(use auto-increment id) - This will reduce the time a bit.
Index that field. - If you use indexed field the query performance will increase.
SELECT * ..., then counting in PHP, requires shoveling all columns of all rows back to PHP. That's a lot of effort for very little gain.
SELECT COUNT(col) ... does the counting in by MySQL, but it must check for whether col is NULL. And it needs to get at the value of col for every row.
SELECT COUNT(*) ... counts the rows by whatever way is most efficient. This involves looking for the 'smallest' index (or the whole table, if no secondary indexes), and counting through it.
You must learn about INDEXes to get anywhere in databases! This is only one minor use for them.

Is there a more eloquent way of doing these MySQL queries?

I'm making 4 individual queries to a MySQL DB, all of which are identical except the WHERE parameters. 2 of which are:
$totalInvites = mysqli_num_rows(mysqli_query($con, "SELECT code FROM invites"));
$usedInvites = mysqli_num_rows(mysqli_query($con, "SELECT code FROM invites WHERE used IS NOT NULL"));
Is there a way of doing the $totalInvites query and from the returned table, do the WHERE call without doing another query?
If that's confusing, this is an example of what I mean:
$query = mysqli_query($con, "SELECT code FROM invites");
$totalInvites = mysqli_num_rows($query);
$usedInvites = mysqli_num_rows($query /*WHERE used IS NOT NULL*/);
I know that's not proper syntax but that's what I was trying say.
If you just want counts then retrieving the entire database and throwing out the results is not really a good idea. Instead jus task for a count:
SELECT COUNT(*) AS count, used
GROUP BY used
This will give you up to two rows, one count for those that are used and one that isn't presuming used has only NULL or a single non-null value.
Use as little SQL as possible:
SELECT if(used is null, 0, 1) AS used, code
FROM invites
And parse result in PHP according to what you need
SELECT
(SELECT code FROM invites) total
(SELECT code FROM invites WHERE used IS NOT NULL) used

Select on empty table but still get column names

I want to do a SELECT on an empty table, but i still want to get a single record back with all the column names. I know there are other ways to get the column names from a table, but i want to know if it's possible with some sort of SELECT query.
I know this one works when i run it directly in MySQL:
SELECT * FROM cf_pagetree_elements WHERE 1=0;
But i'm using PHP + PDO (FETCH_CLASS). This just gives me an empty object back instead of an row with all the column names (with empty values). So for some reason that query doesn't work with PDO FETCH_CLASS.
$stmt = $this->db->prepare ( $sql );
$stmt->execute ( $bindings );
$result = $stmt->fetchAll ( \PDO::FETCH_CLASS, $class );
print_r($result); // Empty object... I need an object with column names
Anyone any idea if there's another method that i can try?
Adding on to what w00 answered, there's a solution that doesn't even need a dummy table
SELECT tbl.*
FROM (SELECT 1) AS ignore_me
LEFT JOIN your_table AS tbl
ON 1 = 1
LIMIT 1
In MySQL you can change WHERE 1 = 1 to just WHERE 1
To the other answers who posted about SHOW COLUMNS and the information scheme.
The OP clearly said: "I know there are other ways to get the column names from a table, but i want to know if it's possible with some sort of SELECT query."
Learn to read.
Anyway, to answer your question; No you can't. You cannot select a row from an empty table. Not even a row with empty values, from an empty table.
There is however a trick you can apply to do this.
Create an additional table called 'dummy' with just one column and one row in it:
Table: dummy
dummy_id: 1
That's all. Now you can do a select statement like this:
SELECT * FROM dummy LEFT OUTER JOIN your_table ON 1=1
This will always return one row. It does however contain the 'dummy_id' column too. You can however just ignore that ofcourse and do with the (empty) data what ever you like.
So again, this is just a trick to do it with a SELECT statement. There's no default way to get this done.
SHOW COLUMNS FROM cf_pagetree_elements;
This will give a result set explaining the table structure. You can quite easily parse the result with PHP.
Another method is to query the infomrmation schema table:
SELECT column_name FROM information_schema.columns WHERE table_name='cf_pagetree_elements';
Not really recommended though!
You could try:
SELECT * FROM information_schema.columns
WHERE table_name = "cf_pagetree_elements"
Not sure about your specific PHP+PDO approach (there may be complications), but that's the standard way to fetch column headings (field names).
this will list the columns of ANY query for PDO drivers that support getColumMeta. I am using this with SQL server and works fine even on very complex queries with aliased tables, sub-queries and unions. Gives me columns even when results are zero
<?php
// just an example of an empty query.
$query =$PDOdb->query("SELECT * from something where 1=0; ");
for ($i=0; $i<$query->columnCount(); $i++) {
echo $query->getColumnMeta($i)['name']."<br />";
}
?>
Even without PDO in the way, the database won't return the structure without at least one row. You could do this and ignore the data row:
SELECT * FROM cf_pagetree_elements LIMIT 1;
Or you could simply
DESC cf_pagetree_elements;
and deal with one row per field.
WHERE 1=0 does not work for me. It always returns empty set.
The latest PDO for SQLSVR definitely works with get column meta.
Simply set up your statement and use this to get an array of useful information:
$stmt->execute();
$meta= array();
foreach(range(0, $stmt->columnCount() - 1) as $column_index)
{
array_push($meta,$stmt->getColumnMeta($column_index));
}
Complete solution for Oracle or MySQL
for any or some columns (my goal is to get arbitrary columns exactly as they are in DB regardless of case)
for any table (w or w/o rows)
$qr = <<<SQL
SELECT $cols
FROM (SELECT NULL FROM DUAL)
LEFT JOIN $able t ON 1 = 0
SQL;
$columns = array_keys($con->query($qr)->fetchAll(PDO::FETCH_ASSOC)[0]);
if($cols === "*") {
array_shift($columns);
}
YOu could use MetaData with;
$cols = mysql_query("SHOW COLUMNS FROM $tableName", $conn);

Mysql SELECT COUNT(*) OR SELECT 1? PDO

It has long been known that PDO does not support COUNT(*) and a query like below would fail as it doesn't return any affected rows,
$q = $dbc -> prepare("SELECT COUNT(*) FROM table WHERE id = ?");
$q -> execute(array($id));
echo $q -> rowCount();
Doing some research I found that you can also get the row count using other methods of count and not using count at all, for example the following query is supposed be the same as above but will return correct for PDO,
$q = $dbc -> prepare("SELECT 1 FROM table WHERE id = ?");
$q -> execute(array($id));
echo $q -> rowCount();
There are various sources on the internet claiming that;
"SELECT COUNT(*)
"SELECT COUNT(col)
"SELECT 1
Are all the same as each other (with a few differences) so how come using mysql which PDO cannot properly return a true count, does
"SELECT 1
work?
Methods of count discussion
Why is Select 1 faster than Select count(*)?
PDO does not support COUNT(*)
WTF? Of course PDO supports COUNT(*), you are using it the wrong way.
$q = $dbc->prepare("SELECT COUNT(id) as records FROM table WHERE id = ?");
$q->execute(array($id));
$records = (int) $q->fetch(PDO::FETCH_OBJ)->records;
If you are using a driver other than MySQL, you might have to test rowCount first, like this.
$records = (int) ($q->rowCount()) ? $q->fetch(PDO::FETCH_OBJ)->records : 0;
Oh. You are confusing everything.
PDO do not interfere with SQL queries. It support EVERYTHING supported by SQL.
When doing COUNT(*) you shouldn't use rowcount at all, as it just makes no sense. You have to retreive the query result instead.
Dunno what "various sources" you are talking about but COUNT(*) and COUNT(col) (and even COUNT(1)) are the same and the only proper way to get count of records when you need no records themselves.
COUNT is an aggregate function, it counts rows for you. So, it returns the result already, no more counting required. Ad it returns just a scalar value in the single row. Thus, using rowcount on this single row makes no sense
SELECT 1 is not the same as above, as it selects just literal 1 for the every row found in the table. So, it will return a thousand 1s if there is a thousands rows in your database. So, rowcount will give you the result but it is going to be an extreme waste of the server resources.
there is a simple rule to follow:
Always request the only data you need.
If you need the count of rows - request count of rows. Not a thousand of 1s to count them later.
Sounds sensible?
Best way I think to test if a line exist in your database is to perform.
SELECT 1 FROM table WHERE condition LIMIT 1
If it find a row it will stop and tell you there is a line. If it don't and you have an index on your where clause column it will also goes very fast to see there are none available.

Count rows from results of a "mysql_query"

If I have this:
$results = mysql_query("SELECT * FROM table_name WHERE id=$id");
is there then any way to check how many rows which have a field-value of "Private" or "Company" ?
I need to show the user how many "Private" and "Company" records where found, without making another query. (There is a column called 'ad_type' which contains either "private" or "company")
I already know the mysql_num_rows for counting all rows!
EDIT:
There are 500thousand records! So maybe an iteration through the result is slow, what do you think?
Thanks for all help :)
The above answers are great and all, but the currently checked answer will work very inefficiently should you be dealing with a large amount of data
Example of the above answer (via Gal)
$results = mysql_query("SELECT *,(SELECT COUNT(*) FROM table_name WHERE column=$value) count FROM table_name WHERE id=$id");
It's good and all, and it returns what you need but the obvious design flaw is that making your SQL server return the results then re-return them and look at just the count is very inefficient for large amounts of data.
Simply do this:
$results = mysql_query("SELECT * FROM table_name WHERE column=$value");
$num_rows = mysql_num_rows($result);
It will yield the same results and be much more efficient in the long run, additionally for larger amounts of data.
You can do something like:
$results = mysql_query("SELECT *,(SELECT COUNT(*) FROM table_name WHERE column=$value) count FROM table_name WHERE id=$id");
in order to fetch the number with sql.
If you don't want to change your query you could do a
$results = mysql_query("SELECT * FROM table_name WHERE id=$id");
$count = mysql_num_rows($results);
steps to get a count():
use mysql_query() to get count,
use mysql_fetch_array() to get the only 1 row
get the only one column of the row, this is the count,
here is an example, which check whether the email is already used:
// check whether email used
$check_email_sql = "select count(*) from users where email='$email'";
$row = mysql_fetch_array(mysql_query($check_email_sql));
$email_count = $row[0];
Iterate through the result set of rows and count the number of occurences of Private and Company in ad_type, respectively?
You can do
SELECT COUNT(*) FROM table_name WHERE id=$id GROUP BY fieldvalue HAVING fieldvalue = "Private"
SELECT COUNT(*) FROM table_name WHERE id=$id GROUP BY fieldvalue HAVING fieldvalue = "Company"
but that would be another query. But if you process the data anyway, you could simply sum up the number of "Private" and "Company" rows after doing the query.
In the case you don't have to get all results, use this.
SELECT ad_type, COUNT(*)
FROM table_name
WHERE (id=$id)
GROUP BY ad_type
HAVING ((ad_type = 'Private') OR (ad_type = 'Company'))
If you still have to fetch all the records where id = $id, it won't work. But executing such a query (once) before fetching the real data should be more efficient than using a subquery.
I guess this query would do the job:
SELECT ad_type, count(*) FROM table_name WHERE id=$id GROUP BY ad_type;
I don't see any reason so far to use HAVING, since you probably want to show the user an overview of all the ad_type's found in DB (at least you didn't mention that there are other values for ad_type then the two given).
I also strongly suggest NOT to use sub-queries; always try to use just one.
If there's one thing that will slow your query down, it's a subquery (or subqueries).
Good luck!
Iterate through the results of the query and keep a count of how many of each show up in local variables.

Categories