PHP + Mysql Select and Count - php

I need get specific values and count all values from a MySQL table, i need get the best performance, my question is: What is better and faster?
- Use two separate queries:
$TBCount = $Resps = $MySQL->query('SELECT COUNT(*) FROM T1');
$Resps = $MySQL->query('SELECT id, name FROM T1 LIMIT 1');
while ($Resp = $Resps->fetch_assoc()) {
...
}
- Use One query with two SELECT:
$Resps = $MySQL->query('SELECT id, name, (SELECT COUNT(*) FROM T1) AS count FROM T1 LIMIT 1');
while ($Resp = $Resps->fetch_assoc()) {
$TBCount = $Resp['count'];
...
}
- Or someone have some best idea?
In the case of "One query, two SELECT", in the "while" loop, how can i get the count value outside of the loop? (to avoid unnecessary rewrite of the variable).

I would suggest first option with minor modification.
$TBCount = $Resps = $MySQL->query('SELECT COUNT(id) FROM T1');
$Resps = $MySQL->query('SELECT id, name FROM T1 LIMIT 1');
while ($Resp = $Resps->fetch_assoc()) {
...
}
note that I have mentioned just id in count query, this can be a good performance impact while dealing with large data.
You can do the same in second option, but as per my thought process second option will give count in all row returned with the main query. And that value will be same for all rows which is really not required.
That is the reason I would go with first option for separate queries.

$Resps = $MySQL->query('SELECT id, name, (SELECT COUNT(*) as tot FROM T1) AS count FROM T1 LIMIT 1');
$Resp = $Resps->fetch_assoc()
$TBCount = $Resp['tot'];
mysqli_data_seek($Resps, 0);
for finding the count value you do not need to repeatedly loop again and again for the rest of the values use the while loop.
while ($Resp = $Resps->fetch_assoc()) {
//rest of your code
...
}

Take a look at SQL_CALC_FOUND_ROWS. It does everything you want. It will give you the total results, even though you're limiting the data returned.
> SELECT SQL_CALC_FOUND_ROWS id, name FROM T1 LIMIT 1
> SELECT FOUND_ROWS();

Related

PHP / SQL - A lot of SQL Queries

On my website, I want to use a lot of different data from my database. Currently, I'm using four queries to gather different data. But is there a way to make it more efficient and put them into one big query? And how would I do that?
Edit: So the answer was to simply put all queries together into one and use as much data manipulation as possible in the database queries, and not in php.
$qry = "SELECT COUNT(*) cnt,
AVG(level) avg_lvl,
SUM(IF(onlinestatus=1, 1, 0)) online_cnt,
(SELECT Max(time) FROM refreshes) refresh_time
FROM players";
foreach ($db->query($qry) as $row){
$amount_total = $row['cnt'];
$average_level = floor($row['avg_lvl']);
$online_amount = $row['online_cnt'];
$milliseconds = $row['refresh_time'] + 1800000;
$update_time = DateTime::createFromFormat('U', intval($milliseconds / 1000));
}
You could combine all queries into one, like this:
$qry = "SELECT COUNT(*) cnt,
AVG(level) avg_lvl,
SUM(IF(onlinestatus=1, 1, 0)) online_cnt,
(SELECT Max(time) FROM refreshes) refresh_time
FROM rookstayers";
foreach ($db->query($qry) as $row){
$amount_total = $row['cnt']
$level = $row['avg_lvl'];
$online_amount = $row['online_cnt'];
$milliseconds = $row['refresh_time'] + 1800000;
$update_time = DateTime::createFromFormat('U', intval($milliseconds / 1000));
}
The last query you have seems to assume there is only one record in the result, as the loop would overwrite the previous result in each iteration. And as there is no order by in that query, it would be a bit of a gamble what the outcome would be. So I have taken the most recent time from the table in case there are multiple records there.
Note that that the above loop only executes once, as there is a guarantee to get exactly one result from the query.
The first and third queries can be combined into one:
select count(*) as num, sum(onlinestatus = 1) as numOnline
from rookstayers;
The second should be an aggregation:
select level, count(*) as cnt
from rookstayers
group by level;
The fourth is also an aggregation; I'm not sure exactly what the data looks like, but it seems to be something like:
select sum(time + 1800000)
from refreshes;
In general, you should do as much data manipulation in the database as you can. That is what databases are designed for.
EDIT:
The first, second, and third can be combined into:
select count(*) as num, sum(onlinestatus = 1) as numOnline,
avg(level) as avgLevel
from rookstayers;

SQL - Get number of rows WHERE "something = something" but not limited by LIMIT

So I had a pretty hard time describing this problem in the title, but basically I need to be able to get the number of rows my SQL query returns from the WHERE clause but is not limited by the LIMIT clause.
Example:
I have a table consisting of 10 posts. They all have column "show" = "true".
I then write my query like this:
$result = "SELECT * FROM table WHERE show = 'true' LIMIT 5";
I now need to get a variable on how many posts would be returned, had the LIMIT not been there.
$count = mysqli_num_rows($result); does not work as it'll only tell me 5 because of the LIMIT. I somehow need to know that there's 10 posts with column "show" = "true", even though my query only returns 5 posts because of the LIMIT.
Help would be very much appreciated!
Use SQL_CALC_FOUND_ROWS and FOUND_ROWS():
select SQL_CALC_FOUND_ROWS t.*
from table t.*
where show = 'true'
limit 5;
Then:
select found_rows();
The documentation is here.
You can use SQL_CALC_FOUND_ROWS and FOUND_ROWS():
SELECT SQL_CALC_FOUND_ROWS * FROM table WHERE show = 'true' LIMIT 5;
SELECT FOUND_ROWS();
http://dev.mysql.com/doc/refman/5.1/en/information-functions.html#function_found-rows
Another option is to issue two distinct queries, one to get the first five (as you have already), and another to get the total count:
SELECT * FROM table WHERE show = 'true' LIMIT 5;
SELECT COUNT(*) FROM table WHERE show = 'true';

Get two types of number of rows with minimum lines

I have the following query.
$sql = "SELECT customer FROM furniture WHERE id = :id AND category = :cat";
$stmt = $connectdb->prepare($sql);
$stmt->execute(array(':id'=>$id, ':cat'=>"1"));
$resulta = $stmt->fetchAll(PDO::FETCH_ASSOC);
$rowcount = count($result);
This works perfectly. But I have a requirement to get the number of rows from WHERE id = :id AND category = :cat as well as to get the number of rows from WHERE category = :cat. Is it possible to do both of them without having to write all those SELECT query lines twice?
You can use conditional sum to get the 2 different counts something as
select
sum(id = :id AND category = :cat) as count1,
sum(category = :cat) as count2
from furniture;
Later you just fetch the records and get the values of count1 and count2
NOTE : If you just do row count it will always return 1 since its using the aggregate function
I would suggest that you write the query as:
select sum(id = :id) as numCatId, count(*) as numCat
from furniture
where cat = :cat;
Putting the condition in the where clause allows MySQL to use an index on furniture(cat) (or better yet furniture(cat, id). In general, it is a good idea to put common filtering conditions in the where clause. This reduces the number of rows needed for processing the rest of the query.

Single mysqli query statement to get total number of rows and limit also

I want to fetch the total count of records in MySQL db table and also use the limit with this. For example, there are 100 rows and the limit I want to use let suppose is 10. I know how to do this using two queries but I want to do this in one go.
SELECT count(*) as total_rows FROM mytable; // gets the total count of rows
SELECT col1,col2 FROM mytable LIMIT 0, 10; // gets the 10 rows of col1,col2
I want to do this in one go. Any idea.
Thanks.
Here is the SQL Fiddle that demonstrates how the below works:
SELECT m.*,
(
SELECT COUNT(*)
FROM mytable AS sm
) AS TotalCount
FROM (
SELECT mt.col1, mt.col2
FROM mytable AS mt
LIMIT 0, 10
) AS m
Have a look at Shayan Husaini's answer on How to get the total row count with MySQLi
I have updated his original answer after trying it out myself. You have to add "SQL_CALC_FOUND_ROWS" after SELECT in your query and add a second query as shown in the code snippet below.
$sql1 = "SELECT SQL_CALC_FOUND_ROWS col1,col2 FROM mytable LIMIT 0, 10";
$sql2 = "SELECT FOUND_ROWS()";
$result1 = $conn->query($sql1);
$result2 = $conn->query($sql2);
$TotalRcount = $result2->fetch_row();
// I have added this next line to correct the answer
$TotalNumRows = $TotalRcount[0];
You can use $result1 to access your results as you normally would.

Which MySQL query is effective to get the total number of records

To get the total number of records, I usually use this query:
$total= mysql_num_rows(mysql_query("SELECT id FROM t_statistic WHERE pageid = $pid"));
but I got one the other query like below:
$data = mysql_fetch_object(mysql_query("SELECT COUNT(id) AS num_rows FROM t_statistic WHERE pageid = $pid"));
$total = $data->num_rows;
Between the two queries above. Which is more quickly and effectively (when the total number of records in the millions)?
I prefer the second query. It gives you already the record count, while the first query gives you the list of IDs (not the count), although it has been filtered but there are some cases when ID exist more than once in the table.
The Second query is quick and efficient:
SELECT COUNT(id) AS num_rows FROM t_statistic WHERE pageid = $pid
If you know about query optimisation. The query will only keeps only count in memory while calculating the answer. And directly gives number of rows.
Where as first query:
SELECT id FROM t_statistic WHERE pageid = $pid
Keeps all the selected rows in memory. then number of rows are calculated in further operation.
So second query is best in both ways.
Definitely the second one.
Some engines, like MySQL can do a count just by looking at an index rather than the table's data.
I've used something like the following on databases with millions of records.
SELECT count(*) as `number` FROM `table1`;
Way faster than: mysql_num_rows($res);
BTW: The * in Count(*) basically means it won't look at the data, it will just count the records, as opposed to Count(colname).
1) SELECT COUNT(*) FROM t_statistic WHERE pageid = $pid" --> count(*) counts all rows
2)SELECT COUNT(id) FROM t_statistic WHERE pageid = $pid" --> COUNT(column) counts non-NULLs only
3) SELECT COUNT(1) FROM t_statistic WHERE pageid = $pid" -->COUNT(1) is the same as COUNT(*) because 1 is a non-null expressions
Your use of COUNT(*) or COUNT(column) should be based on the desired output only.
So. Finally we have result is count(column) is more faster compare to count(*) .

Categories