MySQL: sum() and join from multiple tables - php

Simple to say, but I can't find the syntax or even an example even close! Assume the following tables:
Table:'Red'
Fields: id | sm | md | lg
Data: 1 | 3 | 5 | 7
2 | 9 | 8 | 7
3 | 2 | 4 | 6
Table:'White'
Fields: id | sm | md | lg
Data: 1 | 0 | 0 | 0
2 | 0 | 0 | 0
3 | 0 | 0 | 0
Table:'Blue'
Fields: id | sm | md | lg
Data: 1 | 1 | 1 | 1
2 | 1 | 1 | 1
3 | 1 | 1 | 1
All i want is to total everything up, but keep the rows like the following table:
Table:'Total'
Fields: id | sm | md | lg
Data: 1 | 4 | 6 | 8
2 | 10 | 9 | 8
3 | 3 | 5 | 7
Then create a while loop in PHP to echo back the results. Something like this:
<?php
while($row = mysql_fetch_array($get_totals))
{
echo <td>".$row[sm]."</td><td>".$row[md]."</td><td>".$row[lg]."</td>";
}
?>
I can't figure this out. Any help? I just need a php select statement that will work here.

Not tested but should work:
SELECT id, SUM(sm) as sm, SUM(md) as md, SUM(lg) as lg FROM (
SELECT * FROM Red
UNION ALL
SELECT * FROM White
UNION ALL
SELECT * FROM Blue
) AS somealias
GROUP BY id

Related

how to fetch this query using 2 table

Hy I have 2 table
1.application
id | name | status
====================
1 | morvick | complete
2 | siti | prosess
3 | boby | complete`
2.application_test
id | application_id | test_id | result
======================================
1 | 1 | 1 | 70
2 | 1 | 2 | 80
3 | 1 | 3 | 90
4 | 2 | 1 | 60
5 | 2 | 2 | 80
6 | 2 | 3 | 70
7 | 3 | 1 | 90
8 | 3 | 2 | 70
9 | 3 | 3 | 60
10| 3 | 4 | 80
my Question is :
==================
1. how to find the maximum value at each test_id
2. how I can to get or total applicant_id where status complete
for example to be like this :
test_id | result_max | total_applicant_status(complete)
1 | 90 | 2
2 | 80 | 2
3 | 90 | 2
4 | 80 | 1
SELECT MAX(value) FROM table WHERE test_id = 1;
or perhaps SELECT value, test_id FROM table ORDER BY value DESC;
and for the next part, this may give what you want.
SELECT at.test_id, MAX(at.result), COUNT(IF(status='complete', 1, 0)) FROM application a LEFT JOIN application_test at ON a.id = at.application_id GROUP BY application_id;

how to fetch sum every row mysql

Hy I have 2 table
1.application
id | name | status
====================
1 | morvick | complete
2 | siti | prosess
3 | boby | complete`
2.application_test
id | application_id | test_id | result
======================================
1 | 1 | 1 | 70
2 | 1 | 2 | 80
3 | 1 | 3 | 90
4 | 2 | 1 | 60
5 | 2 | 2 | 80
6 | 2 | 3 | 70
7 | 3 | 1 | 90
8 | 3 | 2 | 70
9 | 3 | 3 | 60
10| 3 | 4 | 80
my Question is :
==================
1. how I can to get sum(result) on each test_id where status complete
2. how I can to get sum(result) on each test_id where status prosess
for example to be like this :
test_id | SUM(result = complete) | SUM(result = proses) |
1 | 90 | 50
2 | 80 | 40
3 | 90 | 60
4 | 80 | 70
Try below query-
SELECT test_id,
SUM(IF(app.status='complete',apt.result,0)) AS complete_sum,
SUM(IF(app.status='process',apt.result,0)) AS process_sum
FROM application_test AS apt
JOIN application AS app ON app.id=apt.application_id
GROUP BY apt.test_id
You can try two query to get sum of result
SELECT test_id , SUM (result)
FROM application a
JOIN application_test t
ON t.test_id = a.id
WHERE a.status = 'complete'
GROUP BY test_id
SELECT test_id , SUM (result)
FROM application a
JOIN application_test t
ON t.test_id = a.id
WHERE a.status = 'prosess'
GROUP BY test_id
if you want in one query
SELECT test_id,
SUM(IF(a.status='complete',result,0)) Completed ,
SUM(IF(a.status='process',result,0)) Process
FROM application a
JOIN application_test t
ON a.id=t.application_id
GROUP BY t.test_id

How to write this complex SQL statement

I have three identical tables in my MySQL table namely
first_term_result, second_term_result and third_term_result
this are the columns in it
exam_type_id | student_id | subject_id | mark |
or example with dummy data
NOTE: there are three different exam type for each subjects (CA1, CA2, CA3 and Exam),
there are three table like this with same thing but different data as it hold data for first term another for second term and the last for third term.
first_term_result:
exam_type_id | student_id | subject_id | mark |
1 | 6 | 7 | 12 |
2 | 6 | 7 | 9 |
3 | 6 | 7 | 13 |
4 | 6 | 7 | 45 |
1 | 4 | 7 | 7 |
2 | 4 | 7 | 5 |
3 | 4 | 7 | 10 |
4 | 4 | 7 | 34 |
second_term_result:
exam_type_id | student_id | subject_id | mark |
1 | 6 | 7 | 15 |
2 | 6 | 7 | 6 |
3 | 6 | 7 | 10 |
4 | 6 | 7 | 50 |
1 | 4 | 7 | 6 |
2 | 4 | 7 | 3 |
3 | 4 | 7 | 9 |
4 | 4 | 7 | 44 |
third_term_result:
exam_type_id | student_id | subject_id | mark |
1 | 6 | 7 | 17 |
2 | 6 | 7 | 8 |
3 | 6 | 7 | 15 |
4 | 6 | 7 | 67 |
1 | 4 | 7 | 12 |
2 | 4 | 7 | 8 |
3 | 4 | 7 | 12 |
4 | 4 | 7 | 50 |
Now what i want to achieve is get the SUM() of first_term_result.mark second_term_result.mark and third_term_result.mark of each students WHERE subject_id=7 group by students name.
another very important problem is i will be calculating the grand sum for each students for first_term+second_term+third_term and also want to be able to order the grand total for that student and the subjects in DESC so i can position them accordingly please if it will be easier on php please let me know.
Thanks
it seems very complex to me but i know there are gurus here who ca achieve this, i read somewhere that it is possible to order by even when rollup is used.
below is my code which doesn't work obviously.
SELECT CONCAT(s.fname,' ',s.mname,' ',s.lname) AS sname,
SUM(f.mark) AS first_total,
SUM(se.mark) AS second_total,
SUM(t.mark) AS third_total
SUM(f.first_total,second.total,third_total) as GT // just to show my intention
FROM students s, first_term_result f, second_term_result se, third_term_result t
WHERE s.studentID=f.student_id AND
s.studentID=se.student_id AND
s.studentID=t.student_id AND
f.subject_id=7 AND
se.subject_id=7 AND
t.subject_id=7
GROUP BY sname ORDER BY GT DESC
SELECT CONCAT(MS.fname,' ',MS.mname,' ',MS.lname) AS sname,
M.FTotal, M.STotal, M.TTotal,
(M.FTotal + M.STotal + M.TTotal) AS GrandTotal
FROM (
SELECT st.studentID,
(
SELECT SUM(f.mark)
FROM first_term_result AS f
WHERE f.subject_id = 7
AND f.student_id = st.studentID
) AS FTotal,
(
SELECT SUM(s.mark)
FROM second_term_result AS s
WHERE s.subject_id = 7
AND s.student_id = st.studentID
) AS STotal,
(
SELECT SUM(t.mark)
FROM third_term_result AS t
WHERE t.subject_id = 7
AND t.student_id = st.studentID
) AS TTotal
FROM students AS st
WHERE st.studentID IN (
SELECT studentID
FROM first_term_result AS fs
WHERE fs.subject_id = 7
AND fs.student_id = st.studentID)
GROUP BY st.studentID
) AS M
JOIN students MS ON M.studentID = MS.studentID
ORDER BY (M.FTotal + M.STotal + M.TTotal) DESC

agent sales report, sums all their sales and minimized display result by total sales

i have 3 table user, products and sales
user
UID | NAME
1 | agent1
2 | agent2
3 | agent3
4 | agent4
5 | agent5
products
PID | PNAME
1 | P1
2 | P2
3 | P3
sales
SID | UID | PID | SALES_CREATED
1 | 3 | 1 | 2013-07-13 01:15:04
2 | 1 | 1 | 2013-07-13 01:25:34
3 | 3 | 1 | 2013-07-13 02:01:34
4 | 3 | 1 | 2013-07-13 02:45:34
5 | 5 | 1 | 2013-07-13 02:56:34
6 | 5 | 1 | 2013-07-13 03:21:34
7 | 2 | 3 | 2013-07-13 03:38:34
8 | 3 | 2 | 2013-07-13 03:51:34
9 | 4 | 2 | 2013-07-13 04:25:34
10 | 3 | 1 | 2013-07-13 04:45:04
11 | 1 | 3 | 2013-07-13 04:55:34
12 | 2 | 2 | 2013-07-13 05:01:34
13 | 1 | 3 | 2013-07-13 05:15:34
14 | 5 | 3 | 2013-07-13 05:36:34
15 | 5 | 3 | 2013-07-13 06:21:34
where the results of sales per agent is: (sort by user UID)
user | P1 | P2 | P3 |
agent1 | 1 | 0 | 2 |
agent2 | 0 | 1 | 1 |
agent3 | 4 | 1 | 0 |
agent4 | 0 | 1 | 0 |
agent5 | 2 | 0 | 2 |
now, i want a result to sort user that has a greatest sale by P1 and a minimum of 3 result only, and the result will be like this
user | P1 | P2 | P3 |
agent3 | 4 | 1 | 0 |
agent5 | 2 | 0 | 2 |
agent1 | 1 | 0 | 2 |
can you guys give me a best mysql_query to show that result?
Oh, something like this...
SELECT uid
, SUM(pid=1) p1
, SUM(pid=2) p2
, SUM(pid=3) p3
FROM sales
GROUP
BY uid
ORDER
BY p1 DESC
, p2 DESC
, p3 DESC;
+-----+------+------+------+
| uid | p1 | p2 | p3 |
+-----+------+------+------+
| 3 | 4 | 1 | 0 |
| 5 | 2 | 0 | 2 |
| 1 | 1 | 0 | 2 |
| 2 | 0 | 1 | 1 |
| 4 | 0 | 1 | 0 |
+-----+------+------+------+
If handling the display logic at the application level, then your query can be simplified to something more scalable, like this...
SELECT uid
, pid
, COUNT(*)
FROM sales
GROUP
BY uid,pid;
I am only answering because (1) I am bored, and (2) I wanted a brain teaser exercise. I typically do not like to answer when people post and run (don't respond to anyone's comments/posts), or provide what they have tried (no query).
If you want better/more help on SO in the future, it would be beneficial to post the query that you have tried, and when using complex/diverse data like this to create a sqlfiddle - http://sqlfiddle.com/
So with that caveat, here is how you can get your desired results
SELECT
user.NAME as user,
SUM(PID=1) as P1,
SUM(PID=2) P2,
SUM(PID=3) P3
FROM
sales
LEFT JOIN
user
ON
user.UID = sales.UID
GROUP BY
sales.UID
HAVING
P1+P2+P3 >= 3
ORDER BY
P1 DESC, P2 DESC, P3 DESC;
and here is the sqlfiddle example that shows it in action - http://sqlfiddle.com/#!2/d3405/8

Custom MySQL Ordering

I have a query that needs a custom sorting, trimmed down to the bare minimums something like:
SELECT u.*, p.*, p.id as product_id
FROM users u, products p
WHERE u.id = p.user_id
ORDER BY product_id DESC
And I get returned a set of rows like:
UserID ProductID
2 5
2 4
3 3
1 2
1 1
But I want it to actually sort SOMETHING like this (so no 2 UserIDs are adjacent to eachother):
UserID ProductID
1 2
2 4
3 3
2 5
1 1
Is this even possible with MySQL, or do I need some PHP magic?
A canonical way of solving this problem is by enumerating the duplicate rows and then ordering by that value:
select t.*
from (SELECT u.*, p.*, p.id as product_id,
row_number() over (partition by u.id order by (select NULL)) as seqnum
FROM users u join
products p
on u.id = p.user_id
) t
order by seqnum, id;
This will work, as long as no one user has a really long sequence (as in your example).
There is no "always-works" solution, because it is easy to come up with a situation where your goal is not possible.
Here fetch your sorted results into an array. Then do something like this.
$records = $res->fetchAll();
$count = count($records);
$records = array_chunk($records, ceil(count($records)/2);
$unsorted = array();
for($x = 0; $x < $count; $x++){
$unsorted[] = $records[$x%2][floor($x/2)];
}
Consider the following...
CREATE TABLE sortable(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,player_id INT NOT NULL);
INSERT INTO sortable(player_id) VALUES (1),(1),(2),(3),(4),(3),(3),(2),(1),(2),(4),(4);
SELECT * FROM sortable;
+----+-----------+
| id | player_id |
+----+-----------+
| 1 | 1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 3 |
| 5 | 4 |
| 6 | 3 |
| 7 | 3 |
| 8 | 2 |
| 9 | 1 |
| 10 | 2 |
| 11 | 4 |
| 12 | 4 |
+----+-----------+
SELECT x.*,COUNT(*) rank FROM sortable x JOIn sortable y ON y.player_id = x.player_id AND y.id <= x.id GROUP BY x.id ORDER BY player_id,rank;
+----+-----------+------+
| id | player_id | rank |
+----+-----------+------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 9 | 1 | 3 |
| 3 | 2 | 1 |
| 8 | 2 | 2 |
| 10 | 2 | 3 |
| 4 | 3 | 1 |
| 6 | 3 | 2 |
| 7 | 3 | 3 |
| 5 | 4 | 1 |
| 11 | 4 | 2 |
| 12 | 4 | 3 |
+----+-----------+------+
SELECT x.*,COUNT(*) rank FROM sortable x JOIn sortable y ON y.player_id = x.player_id AND y.id <= x.id GROUP BY x.id ORDER BY rank;
+----+-----------+------+
| id | player_id | rank |
+----+-----------+------+
| 1 | 1 | 1 |
| 3 | 2 | 1 |
| 4 | 3 | 1 |
| 5 | 4 | 1 |
| 2 | 1 | 2 |
| 8 | 2 | 2 |
| 6 | 3 | 2 |
| 11 | 4 | 2 |
| 9 | 1 | 3 |
| 10 | 2 | 3 |
| 7 | 3 | 3 |
| 12 | 4 | 3 |
+----+-----------+------+
So if your problem is just that you dont want two records with same id should not come next to each other wha I can think simplest is use
SELECT u.*, p.*, p.id as product_id
FROM users u, products p
WHERE u.id = p.user_id
ORDER BY user_id%2 DESC
Or you can even use other number than 2 to meet any certain order you want....

Categories