Counting rows in mysql select based on criteria - php

I'd like to have a SQL select statement (in PHP) that grabs all the data in my table. Then I'd like to be able to look for certain criteria and give me a count of rows that meet that criteria.
I already can do it by using mysql_num_rows and a separate select per criteria, but that seems inefficient. (i'd have dozens of select statements going) Is there a way to do it with just one select statement then use PHP to count the various things I want to count?
Edit:
I dont have any relevant code to post since the only code I do have is just an SQL select that does the filtering for me, and then uses mysql_num_rows to count them. This is what I am trying to avoid doing.
Example Select statement:
SELECT MDate, Type, MW, Region, Status FROM Scheduler WHERE Status = 'Complete';
In the above example I am looking for Status = Complete but I have several status' that I'd like get counts of individually without having to put a separate Select for each status.

You'll need to write some SQL along the lines of ...
SELECT COUNT(*) FROM Table WHERE `status` IN ("Complete", ...)
GROUP BY `status`
Without specifics of your database schema or the code you already have, that's the best answer you'll likely get.

Related

Multiple queries or can be done in one?

I'm not very experienced with more advanced MySQL query stuff.. (mostly basic queries, return and parse response..etc)
However.. I am not clear on the correct approach when I need multiple things (responses) from the database.. Is there a way to get these things from the single query? or do I need to do a new query for each time?
Background:
I use PDO to do a SELECT statement
ie:
$getAllVideos_sql = "SELECT * as FROM $tableName WHERE active IS NOT NULL OR active != 'no' ORDER BY topic, speaker_last, title;";
$getAllVideos_stmt = $conn->prepare($getAllVideos_sql);
$getAllVideos_stmt->execute();
$getAllVideos_stmt->setFetchMode(PDO::FETCH_ASSOC);
$results = $getAllVideos_stmt->fetch(PDO::FETCH_ASSOC);
//parse as I see fit
This gives me my 'chunk of data' that I can pick apart and display as I want.
However.. I want to also be able to give some stats (totals)
For the total (distinct) 'topics'.. as well as total count for the 'titles' (should all be unique by default)
Do I need to do another query, prepare, execute, setFetchMode, fetch all over again?
Is this the proper way to do this? Or is there a way to crib off the initial commands that are already in play?
To be clear, I'm not really looking for a query... I'm looking to understand the proper way one does this.. when they need several pieces of data like I do? multiple queries and executions..etc?
Or maybe it can and -should- be done in one snippet? With an adjustment to the query itself to return sub select/queries info?
this isnt the correct syntax, because it only returns 1 record..(but the total topic count seems to be correct, even though I only get 1 record returned)
SELECT *, count(DISTINCT topic)as totalTopics, count(DISTINCT title)as totalTitles FROM $tableName;
Maybe this the more proper approach? Try to include these totals/details in the main query to pick out?
Hope this makes sense.
Thanks
I don't think you're going to get anything very clean that'll do this, however something like this might work:
SELECT * from $Table t
INNER JOIN (
SELECT COUNT(DISTINCT Topic) as TotalTopics FROM $Table
) s ON 1 = 1
INNER JOIN (
SELECT COUNT(DISTINCT Title) as TotalTitles FROM $Table
) f ON 1 = 1
WHERE ( Active IS NOT NULL ) AND Active != 'no'
Especially with web applications, many people are regularly doing counts or other aggregations somewhere along the way. Sometimes if it is a global context such as all topics for all users, having some stored aggregates helps rather than requerying all record counts every time.
Example. If you have a table with a list of "topics", have a column in there for uniqueTitleCount. Then, based on a trigger, when a new title is added to a topic, the count is automatically updated by adding 1. You can pre-populate this column by doing a correlated update to said "topics" table, then once the trigger is set, you can just have that column.
This also works as I see many times that people want "the most recent". If your system has auto-increment IDs in the tables, similarly, have the most recent ID created for a given topic, or even most recent for a given title/document/thread so you don't have to keep doing something like.
select documentID, other_stuff
from sometable
where documentID in ( select max( documentID )
from sometable
where the title = 'something' )
Use where these make sense then your optimization pull-downs get easier to handle. You could even have a counter per document "title" and even a most recent posting date so they can quickly be sorted based on interest, frequency of activity, whatever.

Mysql query very slow (group by)

mysql query very slow but i use "group by" function...
i remove group by query and query very fast.
How can I solve this problem?
my query code:
$myquery1 = mysql_query("SELECT * FROM konucuklar
WHERE status=''
and category='football'
GROUP BY matchhour
ORDER BY id asc");
while($myquery1record = mysql_fetch_array($myquery1)){
$myquery2 = mysql_query("SELECT * FROM konucuklar
WHERE mactarihi='$bugunt'
and statu=''
and kategori='futbol'
and macsaati='$myquery1record[matchhour]'
ORDER BY id asc");
$toplams=#mysql_num_rows($myquery2);
while ($myquery2record=mysql_fetch_array($myquery2)) {
// code
}
}
}
Your first query does not comply with SQL standards and will be processed by mysql only if strict sql mode is not enabled.
You are issuing the 2nd query in a loop based on the results returned by the 1st query. So, if the 1st query returns 10 rows, then you will execute the 2nd query 10 times. This is very slow. You should rewrite the 2 queries as one, since both queries query the same table and have almost the same where criteria.
No idea what the 2nd while loop does, as I can't see where $listele is defined.
The slow down might not be related to the GROUP BY clause. Try adding an index on columns you need to .
Link to understand index : http://www.tutorialspoint.com/sql/sql-indexes.htm
MySQL Profiling might also help you in your endeavour
Your queries are not optimized and probably could be done better in other way incluiding using only one composed query (JOIN) to fetch all data at once.
Also if your tables have lots of items is good practice to create INDEXES to the fields uses in the common queries for the filter to make the search faster.
Example, your firs select has this complexity (and probably is not well formed)
SELECT * FROM konucuklar WHERE status=''
and category='football'
GROUP BY matchhour
ORDER BY id asc
But is used only to get the matchhour for the second query. The minimal optimization is to use a query to fetch only the required field.
SELECT DISTINCT matchhour FROM konucuklar WHERE status='' and category='football'

Codeigniter ActiveRecord duplicate,change,execute MySQL query

I am using the ActiveRecord library that comes with the PHP framework CodeIgniter. I frequently find myself needing to query the database for a number of rows using a LIMIT clause, but also needing to know the total number of rows I would have pulled had I not included the LIMIT clause. For example, this is frequently the case when I provide pagenation for many results. I only want to pull 20 records at a time, but I also need to know how many rows there are in total which match my query where clause. I need to create 2 slightly different queries, a count query:
SELECT * FROM table WHERE [where_clause];
And a 'paged' query:
SELECT * FROM table WHERE [where_clause] LIMIT 0,20;
Is there an elegant solution to this problem with ActiveRecord? There doesn't seem to be anything out of the box which will help me. Obviously I can write around the problem with my own PHP but it would be ideal if I could take advantage of some aspect of the library to not have to duplicate code, etc.
Answer my own question, best way is to use SQL_CALC_FOUND_ROWS like so, Add this select call to your query:
$this->db->select('SQL_CALC_FOUND_ROWS *',false);
And then immediately afterwards to get the count:
$count = $this->db->query("SELECT FOUND_ROWS() AS count")->row('count');

Combining different table queries in db with PHP and displaying all results on one page

I have been trying to create a database for fun to get a better understanding of databases and using PHP to query them for a website I'm messing around with. Pretty much I have one database with 4 tables when a user enters a search term in a PHP search box my code searches the database for any entries containing the search term. Now I can easily get my code to search individual tables, but I cannot seem to get it to search all 4 tables and display the results on the same page.
info: making a database for skyrim
Table names: classes, powers, skills, shouts
column names: name, information
Here is a snippet of the code I have that works so far:
$raw_results = mysql_query("
SELECT *
FROM `xaviorin_skyrim`.`shouts` , `xaviorin_skyrim`.`classes`
WHERE (CONVERT(`UID` USING utf8) LIKE '%".$query."%' OR
CONVERT(`Name` USING utf8) LIKE '%".$query."%' OR
CONVERT(`Information` USING utf8) LIKE '%".$query."%')
") or die(mysql_error());`
Literally all I thought I would need to do is change the table name from "shouts" to say "classes" in a new raw_results line of code but that didn't work. I have attempted unions and joins and either keep screwing them up or just don't understand how to properly format them.
echo "<p><h3>".$results['Name']."</h3>".$results['Information']."</p>";
The code above this text is what displays the results on the page on my website... it works but I don't know how to combine the information from all 4 tables into one page. If I'm going about this in the wrong way and anyone can point me in the right direction I would GREATLY appreciate it... I've been trying to research the problem without finding a proper answer for near a month now.
The problem with your approach is that relational databases do a cross join when there are several query results from two different tables. So basically every match in one table will be combined with every match from the second table. When you have 3 entries in the first and 4 in the second table, you will get 3 * 4 = 12 entries in your query result. If you add more tables, you get even more results. You want to do a full text search in several tables that are totally unrelated, thus creating some kind of non-existing relation via cross joining them will not be useful.
What you actually want to do is a UNION ALL (UNION is slower because it prunes duplicates) of several queries:
SELECT name, information, 'shouts' AS tablename FROM shouts WHERE ...
UNION ALL
SELECT name, information, 'classes' AS tablename FROM classes WHERE ...
This will do search queries on every single table and then place the results in a single result. Also note that I added a third column to each query to ensure that the originating table is not lost after merging the results.
Unless you need to do some sorting afterwards, I would suggest that you do all statements separately. Combining them this way will most likely make the post-processing more complex. And several single queries will also be faster than one big query with UNION statements.
And as I mentioned in the comments: Don't use mysql_* functions!

Selecting just one row from a joined MySQL query

I am trying to make a social networking site in PHP/MySQL. I am currently developing status update and comments on status's system. I am trying to show all status of mine and comments on certain status. For doing that I have two tables: comment and user_status.
I have used this MySQL query,
SELECT * FROM user_status LEFT JOIN
comment ON id_status = comment.status_id
WHERE sender_id = '$id2'
OR receive_id = '$id2'
/* $id2 is my id */
I have successfully showed status and one comment. But the problem is, when the number of comments are more than one, then the status shows more than one times. How much same status will be showed depends on how much comments available on certain status. But I would like to be able to display same status only one time, and display more than one comments (if available) on certain status.
This isn't so much a PHP problem as it is confusion about how SQL joins work.
It sounds as if what you really want is not so much a join but a distinct set of records from two tables. Until your SQL skils develop a little more, consider simplifying things by making two queries -- one each for comment and user_status. Also consider requesting just the specific fields you're interested rather than using SELECT *.
Here is a visual explanation of different SQL joins, in case you want to pursue this with a single query.
I assume that you are not displaying the raw results from the query, but rather are piping them to an html page to display. Display only the most recent status in a textbox. then display thin a table or list an ordered list of the comments.
Your query is correct.

Categories