Help getting "correct" mysql count from database - php

Hey guys, I have this query.
"SELECT COUNT(purchase_log.id), purchase_log.date_purchased, purchase_log.total_cost, purchase_log.payment_status, cart_contents.product_name, members.first_name, members.last_name, members.email FROM `purchase_log` LEFT JOIN `cart_contents` ON purchase_log.id = cart_contents.purchase_id LEFT JOIN `members` ON purchase_log.member_id = members.id";
As you can see I have 3 different tables I am trying to draw data from. After running this query, it returns with the count of 9. That is actually the total number of rows in the table "cart_contents" but what I want is for it to return 5 because the table "purchase_log" contains the total transaction per row and each transaction can have 1 or more rows in table "cart_contents".
So how can I form the query to count the right amount?

You can try,
SELECT COUNT(DISTINCT
purchase_log.id),
purchase_log.date_purchased,
purchase_log.total_cost,
purchase_log.payment_status,
cart_contents.product_name,
members.first_name, members.last_name,
members.email FROM purchase_log LEFT
JOIN cart_contents ON
purchase_log.id =
cart_contents.purchase_id LEFT JOIN
members ON purchase_log.member_id =
members.id

Related

mysql join where for 1 table

I have 2 tables, student and grades
student table contains id, name and date_of_birth
grades table contains id, student_id, grade and course
Actual table contain more data.
I have a query like
SELECT s.*, AVG(g.grade) as average_grade
FROM student s LEFT JOIN grade g ON s,id = g.student_id
WHERE g.course = 'mathematics' and s.id = 1
With this I could get the data i needed which are student details and the average grade, then come the problem where when the course = "mathematics" is not found in the grades table, the query will return NULL. My question is, is there a way for me to get the s.id = 1 details together with NULL average instead of all NULL value?
I would prefer if it is able to do it with 1 query, as because in my current I am using subquery and it takes very long to get the data. My main objective is to get more faster speed if you have better way instead of using 1 query feel free to comment your idea. In addition I have tried multiple query and sub query to get all the data but it all take too long.
Move your filter criteria for g.course = 'mathematics' in joining part
SELECT s.*, AVG(g.grade) as average_grade
FROM student s
LEFT JOIN grade g ON s.id = g.student_id AND g.course = 'mathematics'
WHERE s.id = 1
Your query produces result as inner join not left because putting g.course = 'mathematics in where clause turns your left join to inner join, Moving this part in on clause will still return data from student table if there were no rows found from grade table with course = 'mathematics'
If the course is not 'mathematics' you would still get the student data if you put it like this.
SELECT s.*, AVG(g.grade) as average_grade
FROM student s LEFT JOIN grade g ON s,id = g.student_id
WHERE (g.course = 'mathematics' AND s.id = 1) OR s.id = 1

JOIN shows data twice in mysql?

SELECT *
FROM `all_salary_slip_details` `assd`
INNER JOIN `employee_master` `em` ON `assd`.`EMPLOYEE_ID` = `em`.`EMPLOYEE_ID`
INNER JOIN `employee_details` `ed` ON `assd`.`EMPLOYEE_ID` = `ed`.`EMPLOYEE_ID`
INNER JOIN `organizations` `o` ON `o`.`ORG_ID` = `assd`.`ORG_ID`
INNER JOIN `months` `mo` ON `mo`.`id` = `assd`.`PAY_MONTH`
This is my query to fetch data from db. I have only 4 rows but in my view I get 48 rows. I dont understand why this happens.
You need to use a GROUP BY clause on a column, then your query will only return a single row for each unique entry in that column.
In your case I'm guessing it would make sense to use the employee name.
What result does this query output?
SELECT assd.PAY_YEAR, assd.PDF, em.EMPLOYEE_NAME, o.ORG_NAME, mo.month_name
FROM all_salary_slip_details assd
INNER JOIN employee_master em
ON assd.EMPLOYEE_ID = em.EMPLOYEE_ID
INNER JOIN organizations o
ON o.ORG_ID = assd.ORG_ID
INNER JOIN months mo
ON mo.id = assd.PAY_MONTH
GROUP BY em.EMPLOYEE_NAME
You will get 1 row returned in your query for each record in a joined table that matches the join condition.
So, if you have multiple records in any one of the employee_master, employee_details, organisations or months tables that match those in all_salary_slip_details you will get additional rows returned. Look at the rows returned, you will see differences in each and where they differ will tell you where the join condition for the table isn't specific enough to return a single row.

SQL query to get all rows that have data linked by a FK in another table

I have three tables: Station, MonthlyNormalData and SubArea. I'm trying to get all stations in a sub area that have at least one monthly data tied to it. With the following query, I am able to get all stations in a sub area, but this is disregarding the part about monthly data ($region is a variable containing the region name in my PHP script):
SELECT S.station_id, S.name, SA.sub_area_name
FROM dev.Station AS S
INNER JOIN dbo.SubArea AS SA ON S.sub_area_id = SA.sub_area_id
WHERE sub_area_name = '$region'
I have also tried the following query, but it returns one row for each monthly data associated with a station, which is not really what I am looking for (only looking for something that sends me the names of the stations that have at least one monthly data associated to it, not all rows containing that data):
SELECT S.station_id, S.name, SA.sub_area_name
FROM dev.Station AS S
INNER JOIN dbo.SubArea AS SA ON S.sub_area_id = SA.sub_area_id
INNER JOIN data.MonthlyNormalData as MND ON MND.station_id = S.station_id
WHERE sub_area_name = '$region' AND MND.value IS NOT NULL
What would be the query I would need to run to only have one row per station that have a monthly data associated with it within a certain sub area?
You can just use DISTINCT in your second query to remove duplicated rows:
SELECT DISTINCT ...
Since you are only returning records from the tables Station and SubArea using Distinct will work for you.
SELECT distinct S.station_id, S.name, SA.sub_area_name
FROM dev.Station AS S
INNER JOIN dbo.SubArea AS SA ON S.sub_area_id = SA.sub_area_id
INNER JOIN data.MonthlyNormalData as MND ON MND.station_id = S.station_id
WHERE sub_area_name = '$region' AND MND.value IS NOT NULL
Another way to go about it would be to use exist
SELECT S.station_id, S.name, SA.sub_area_name
FROM dev.Station AS S
INNER JOIN dbo.SubArea AS SA ON S.sub_area_id = SA.sub_area_id
WHERE exists (select 1 from data.MonthlyNormalData where station_id = S.station_id) and
sub_area_name = '$region'

get count of posts based on count(*)

i am trying to get number of posts that i have
Here is my query
$Query="
SELECT t.*,u.*,c.*
FROM posts as t
LEFT JOIN relations as r on r.post_id = t.post_id
LEFT JOIN users as u on t.auther_id = u.auther_id
LEFT JOIN categories as c on c.cate_id = r.cate_id
GROUP BY t.post_id
";
$Query=mysql_query($Query);
$numberOfPosts=mysql_num_rows($Query);
This query is works very well
but i am trying to convert it, i want make it faster
i want use count(*) instead of t.*
because when i use t.*, it gets the full data of posts and categories
but i want to get count only, So i decided to use count(*) but i don't know how to use it with query like this
Edit
i've replaced SELECT t.*,u.*,c.* with SELECT count(t.*)
But i got mysql Error Warning: mysql_fetch_assoc(): supplied argument
Edit 2:
i am trying SELECT count(t.post_title)
I Got this results
Array ( [count(t.post_id)] => 10 )
But i have only 2 posts!
$Query="
SELECT t.*,u.*,c.*
FROM posts as t
LEFT JOIN relations as r on r.post_id = t.post_id
LEFT JOIN users as u on t.auther_id = u.auther_id
LEFT JOIN categories as c on c.cate_id = r.cate_id
GROUP BY t.post_id
";
$Query=mysql_query($Query);
$numberOfPosts=mysql_num_rows($Query);
Let's take a step back and analyze this query for a moment.
You're selecting everything from three out of four tables used in the query. The joins create some logic to limit what you select to the proper categories, authors, etc. At the end of the day you are getting a lot of data from the database, then in PHP simply asking it how many rows were returned (mysql_num_rows). Instead, what #Dagon is trying to suggest in comments, is that you have MySQL simply count the results, and return that.
Let's refactor your query:
$query = "
SELECT COUNT(t.post_id) AS qty
FROM posts as t
LEFT JOIN relations AS r ON r.post_id = t.post_id
LEFT JOIN users AS u ON t.auther_id = u.auther_id
LEFT JOIN categories AS c ON c.cate_id = r.cate_id
GROUP BY t.post_id
";
$result = mysql_query($query);
$result_row = mysql_fetch_assoc($result);
$numberOfPosts = $result_row['qty'];
(You could also use Barattlo's custom execute_scalar function to make it more readable.)
I would need to see your table structures to be of more help on how to optimize the query and get the desired results.
try doing this:
$Query="
SELECT count(t.*) as count_all
FROM posts as t
LEFT JOIN relations as r on r.post_id = t.post_id
LEFT JOIN users as u on t.auther_id = u.auther_id
LEFT JOIN categories as c on c.cate_id = r.cate_id
GROUP BY t.post_id
";
$Query=mysql_query($Query);
$numberOfPosts=mysql_num_rows($Query);
You want to do
SELECT count(t.id) AS count FROM ....
//do query with PDO or whatever you are using
$rows = mysql_fetch_assoc();
$num_rows = $rows['count'];
You should probably simply use
SELECT count(*) as postingcount FROM posts
Why?
Because you do not have a WHERE clause, so there are no restrictions. Your JOINS do not ADD more rows to the resultset, and in the end your GROUP BY merges every duplicate occurance of a post_id that might have occurred because of joining back into one row. The result should only be counted, so assuming that the real number you want to know is the number of data sets inside the table posts, you do not need any join, and doing count(*) really is a very fast operation on tables in MySQL.
Remember to check if mysql_query returns false, because then you have to check mysql_error() and see why your query has an error.

MySQL Count Query not working but its display records list

I try to use this Query to get Number of Records bu tits not display count in phpMyAdmin
And also give me the wrong result when i try to remove LIMIT from Query..
SELECT COUNT(*) as `num` FROM fm_detail
LEFT JOIN lang ON lang.l_id = fm_detail.language_id
LEFT JOIN country ON country.c_id = fm_detail.country_id
LEFT JOIN users ON users.usr_id = fm_detail.submitter_id
LEFT JOIN category ON category.cat_id = fm_detail.category_id
INNER JOIN city ON fm_detail.city_fm = city.city_id
where 1=1 AND fm_detail.category_id = '1' LIMIT 10 , 5
This query did not give me any Record Count..
But when i use..
SELECT * FROM fm_detail
LEFT JOIN lang ON lang.l_id = fm_detail.language_id
LEFT JOIN country ON country.c_id = fm_detail.country_id
LEFT JOIN users ON users.usr_id = fm_detail.submitter_id
LEFT JOIN category ON category.cat_id = fm_detail.category_id
INNER JOIN city ON fm_detail.city_fm = city.city_id
where 1=1 AND fm_detail.category_id = '1' LIMIT 10 , 5
This give me the Records list in PHPMYADMIN..
I don't know how to use this query to fix my problem.
Please help me asap..
Thanks,
Because you use COUNT function (which in your case returns one row) and LIMIT clause that starts from 10 record. So, you do not get any records at all.
About the LIMIT... maybe select distinct will help to get the right count. Joins sometimes create duplicated rows.

Categories