MySQL Multiplied query result (LEFT JOIN, SUM, COUNT, GROUP BY) - php

Trying to get a simple SUM and COUNT from a table that takes a couple of joins and some math. I can't get it right.
I have 4 tables:
USERS
user_id, name
1, user1
2, user2
3, user3
4, user4
RESULTS
user_id, plus, minus
1, 1, 0
1, 1, 0
1, 1, 0
3, 0, 1
3, 1, 0
3, 1, 0
3, 1, 0
NOTES
user_id, note
1, lorem ipsum
3, abc
1, qwerty
3, qwerty
MESSAGES
user_id, message
1, lorem ipsum
3, abc
1, qwerty
3, qwerty
3, qwerty
3, qwerty
3, qwerty
I would like to sum all the result of subtracting plus from the minus, amount of notes and amount of messages of users.
My query:
SELECT u.`user_id`, SUM(w.`plus`-w.`minus`), COUNT(g.`user_id`), COUNT(m.`user_id`)
FROM `users` u
LEFT JOIN `results` w ON u.`user_id` = w.`user_id`
LEFT JOIN `notes` g ON u.`user_id` = g.`user_id`
LEFT JOIN `messages` m ON u.`user_id` = m.`user_id`
GROUP BY 1
Expected result should looks like:
user_id: sum(plus-minus) amount of notes, amount of messages
1: 3, 2, 2
3: 2, 2, 5
unfortunatelly query returns:
user_id: sum(plus-minus) amount of notes, amount of messages
1: 12, 12, 12
3: 20, 40, 40
Any help is greatly appreciated.

You should manually count the records in a subquery for every user_id so you will get correct value.
SELECT u.user_ID, u.Name,
COALESCE(r.totalResult, 0) totalResult,
COALESCE(n.totalNotes, 0) totalNotes,
COALESCE(m.totalMessages, 0) totalMessages
FROM users u
LEFT JOIN
(
SELECT user_ID, SUM(plus - minus) totalResult
FROM Results
GROUP BY user_ID
) r ON u.user_ID = r.user_ID
LEFT JOIN
(
SELECT user_ID, COUNT(*) totalNotes
FROM Notes
GROUP BY user_ID
) n ON u.user_ID = n.user_ID
LEFT JOIN
(
SELECT user_ID, COUNT(*) totalMessages
FROM Messages
GROUP BY user_ID
) m ON u.user_ID = m.user_ID
But if you have set an auto_incremented column in every table, the subquery isn't needed since you can distinctly count from it.

Related

How can I join a table to itself having it look like it's three tables?

Honestly, I don't know how to join a table to itself to solve this problem.
I have a table that stored it's record in the format below:
I want to query the table and display it's record in this format:
This is what I have tried so far
Select f.score as first_term, s.score as second_term, t.score as term_tetm from table f left join table s left join table t using (studentid) where studentid = 001 group by subject
You can get the result by grouping on the subject name, but then you will have to use an aggregate function. Here is an example:
CREATE TABLE #StudentGrades
(
[SUBJECT] VARCHAR(50),
[STUDENT_ID] VARCHAR(3),
[SCORE] INT,
[TERM] VARCHAR(50)
)
INSERT INTO #StudentGrades ([SUBJECT], [STUDENT_ID],[SCORE],[TERM])
VALUES ('English', '001', 50, '1st_Term'),
('Mathematics', '001', 40, '1st_Term'),
('French', '001', 60, '1st_Term'),
('English', '001', 60, '2nd_Term'),
('Mathematics', '001', 50, '2nd_Term'),
('French', '001', 50, '2nd_Term'),
('Computer', '001', 70, '2nd_Term'),
('English', '001', 65, '3rd_Term'),
('Mathematics', '001', 60, '3rd_Term'),
('French', '001', 70, '3rd_Term'),
('Computer', '001', 80, '3rd_Term')
SELECT [SUBJECT],
MAX(CASE WHEN [TERM] = '1st_Term' THEN [SCORE] END) AS '1ST_TERM',
MAX(CASE WHEN [TERM] = '2nd_Term' THEN [SCORE] END) AS '2ND_TERM',
MAX(CASE WHEN [TERM] = '3rd_Term' THEN [SCORE] END) AS '3RD_TERM'
FROM #StudentGrades
GROUP BY [SUBJECT]
ORDER BY [SUBJECT]
This is a simple solution but it works. Selecting student, subject and then sub-select for each of the terms. Finally, we DISTINCT it because there will be repetitions due to same subject on more than 1 term.
SELECT
DISTINCT
student_id,
`subject`,
(SELECT score FROM test AS t2 WHERE t2.student_id = t1.student_id AND t1.subject=t2.subject AND t2.term=1) AS term1,
(SELECT score FROM test AS t2 WHERE t2.student_id = t1.student_id AND t1.subject=t2.subject AND t2.term=2) AS term2,
(SELECT score FROM test AS t2 WHERE t2.student_id = t1.student_id AND t1.subject=t2.subject AND t2.term=3) AS term3
FROM
test AS t1

Left JOIN 2 tables with more than one result

I have 2 tables
fist one customer
id, name
1, Adam
2, Sam
3, Erik
second one orders
id, father_id , order
1, 1, 1000
2, 1, 2000
4, 2, 4000
5, 3, 600
6, 3 , 433
the php output should be
Adam : orders : 1 - 1000 , 2 - 2000
Sam : orders : 4 - 4000
Erik : orders : 5 - 300 , 6 - 433
How could I do the output in this case using left join method
Im lost
SELECT
c.id,
c.name,
GROUP_CONCAT(CONCAT(o.id,' - ',o.order))
FROM customer c
LEFT JOIN orders o
ON c.id = o.father_id
GROUP BY c.id

MySQL query to get sum of differences between column and AVG of same column

I have a table which contains the scores by user, for a game:
UserID (Integer)
MatchId (Integer)
Score (Double)
I'd like to getter sum each user's "points above average" (PAA) - the
amount by which a user's score was above or below the average.
So you'd need to calculate the average of 'Score' for each 'MatchId',
then for each row in the table calculate the amount by which the
'Score' differs from the match average. And then sum that PAA value by
user.
Is it possible to do this via a MySQL query? Or do I need PHP? If it can be done by query, what would that query look like?
plan
compute avg scores by match
join user scores to avg scores and compute sum of derived difference field by userid
setup
create table scores
(
UserID integer not null,
MatchId integer not null,
Score decimal(5, 2) not null,
primary key ( UserID, MatchId )
);
insert into scores
( UserID, MatchId, Score )
values
( 1, 1, 22.1 ),
( 2, 1, 36.0 ),
( 3, 1, 35.3 ),
( 1, 2, 50.0 ),
( 2, 2, 39.8 ),
( 3, 2, 42.0 )
;
query
select s.UserID, sum(s.Score - avgs.avg_score) as paa
from scores s
inner join
(
select MatchId, avg(Score) as avg_score
from scores
group by MatchId
) avgs
on s.MatchId = avgs.MatchId
group by s.UserID
;
output
+--------+-----------+
| UserID | paa |
+--------+-----------+
| 1 | -2.966666 |
| 2 | 0.733334 |
| 3 | 2.233334 |
+--------+-----------+
sqlfiddle

MySQL query to get SUM and merged results from 3 tables

I am having 3 tables in my MySQL DB. The Tables and columns are like in sample below
Table User
id, name, dob, gross_salary
----------------------------------
1, test1, 12 Mar 90, 50000
2, test2, 10 Jan 85, 45000
Table Wage
ida, date, allowence_paid
------------------------------
1, 10 Jul 13, 12000
2, 10 Aug 13, 23000
2, 12 Aug 13, 1000
1, 15 Aug 13, 15000
Table Loan
id, date, loan_amount
--------------------------
2, 05 Jul 13, 500
1, 05 Aug 13, 2500
1, 06 Aug 13, 1200
I need these three tables merged in results for Aug 13 like
id, name, allowence_paid, loan_Amount, paid
--------------------------------------------
1, test1, 15000, 3700, 11300
2, test2, 24000, 0, 24000
SUM of two columns from two different tables joined to another table is required in my case.
Can I get help for the query? I have experimented as per MySQL JOIN with SUM and 3 tables and failed.
This seems to work:
select *, allowence_paid-loan_amount as paid
from
(
select User.id as UserId, User.name as UserName, sum(allowence_paid) as allowence_paid
from Wage join User on Wage.ida=User.id
and Wage.date between '2013-08-01 00:00:00' and '2013-08-31 23:59:00'
group by UserId
) W JOIN
(
select User.id as UserId, User.name as UserName, sum(coalesce(loan_amount,0)) AS loan_amount
from Loan right outer join User on Loan.id=User.id
and Loan.date between '2013-08-01 00:00:00' and '2013-08-31 23:59:00'
group by UserId
) L ON W.UserId = L.UserId
SQL fiddle here.

MySQL Left Join with WHERE and Greater than

I want to do a LEFT JOIN and then sort my display by a rank column and also show items only if the qty column is greater than 0
SELECT
*
FROM `product`
LEFT JOIN `stock`
ON `product`.`product_id`=`stock`.`pid`
AND `qty` > 1
ORDER BY `product`.`rank` ASC
Product Table
product_id
name
rank
price
Stock Table
pid
price_sale
qty
Product Table
12, Pen, 2, 53.00
13, Pen, 1, 58.00
14, Pen, 3, 25.00
Stock Table
12, 10.00, 5
13, 18.00, 15
My results do not appear.
It should display:
12, Pen, 2, 53.00, 12, 10.00, 5
13, Pen, 1, 58.00, 13, 18.00, 15
Use Below Query
SELECT * FROM `product`
LEFT JOIN `stock`
ON `product`.`product_id`=`stock`.`pid`
WHERE `stock`.`qty` > 0
ORDER BY `product`.`rank` ASC
The AND should be a WHERE like this :
SELECT *
FROM `product`
LEFT JOIN `stock` ON `product`.`product_id`=`stock`.`pid`
WHERE `qty` > 1
ORDER BY `product`.`rank` ASC

Categories