SQL LEFT JOIN 3 TABLES AND USING COUNT AND GROUP BY - mysql

I have 3 tables, users, branches and states
TABLE USERS
name code_branch
1 ANA 100
2 BEN 101
3 CARLA 102
4 DAN 100
5 ED 100
TABLE BRANCHES
code_branch branch_name code_state
1 100 BRANCH 100 A
2 101 BRANCH 101 A
3 102 BRANCH 102 C
4 103 BRANCH 103 D
5 104 BRANCH 104 E
6 105 BRANCH 105 F
TABLE STATES
code_state state_name
1 A STATE A
2 B STATE B
3 C STATE C
4 D STATE D
5 E STATE E
and i want the result as per below
state_name total_user
1 STATE A 4
2 STATE B 0
3 STATE C 1
4 STATE D 0
5 STATE E 0
My sql
SELECT s.code_state, COUNT(u.code_branch ) AS total
FROM ((states s
LEFT JOIN branches b ON s.code_state = b.code_state )
LEFT JOIN users u.code_branch = b.code_branch)
GROUP BY s.code_state;
and the result is
STATE TOTAL
A 4
B 0
C 1
D 0
E 0
I Want to show state_name instead of code_state in my query result above.
then i change on the first line like this
SELECT **s.state_name**, COUNT(u.code_branch ) AS total
and like this
SELECT **s.state_name, s.code_state** , COUNT(u.code_branch ) AS total
but get the error
Msg 8120, Level 16, State 1, Line 44
Column 's.state_name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Try adding the group by in the select statement?
SELECT **s.state_name, s.code_state** , COUNT(u.code_branch ) AS total
Group by **s.state_name, s.code_state**

Related

MySQL join based on where from 2nd table

I have two tables as follows:
docs
id
carid
name
1
1
doc1
2
1
doc2
3
2
doc3
4
1
doc4
5
5
doc5
cars
carid
parentid
name
1
4
car1
2
5
car2
3
4
car3
4
4
car4
5
5
car5
Question: I want to write a query in mysql where I can pass the carid in where clause and get all the rows from docs table where the parentid is same as that of the passed carid.
Desired Outcome If I pass carid=3 then the rows 1,2,4 from docs table should be returned as the parentid is 4 for carids 1,3,4.
Simillarly, If I pass carid=2 then the rows 3,5 from docs table should be returned as the parentid is 5 for carids 2.5.
You need to join the cars-table twice. First for the condition and second for the parent:
select d.*
from cars c
join cars p on p.parentid=c.parentid
join docs d on d.carid=p.carid
where c.carid=3
You're thinking about this a little wrong in the aspect of a relational database .. You SHOULD have 4 tables:
docs
doc_id
name
1
doc1
2
doc2
3
doc3
4
doc4
5
doc5
cars
car_id
name
1
car1
2
car2
3
car3
4
car4
5
car5
cars_to_docs
car_id
doc_id
1
1
1
2
1
4
2
3
5
5
parents_to_car
car_id
parent_id
1
4
2
5
3
4
4
4
5
5
Then you could simply use a basic JOIN
SELECT b.doc_id FROM test.docs a
LEFT JOIN test.cars_to_docs b
ON a.doc_id = b.car_id
LEFT JOIN test.parents_to_car c
ON c.car_id = b.car_id
LEFT JOIN test.cars d
ON c.car_id = d.car_id
WHERE c.parent_id = (SELECT parent_id FROM test.parents_to_car WHERE car_id = 3)
This will give you your output of 1,2,4

How to count max value in one month from 2 table

I have 2 table on my transaction
Table One
id | date | cust_id | driver_number
1 2019-01-02 1 F 3350 NN
2 2019-04-02 2 AX 111 Z
3 2019-05-02 3 S 787 X
4 2019-05-02 4 T 9090 M
5 2019-06-02 3 P 8989 L
Table Two
driver_number | price
F 3350 NN 350000
AX 111 Z 400000
S 787 X 375000
T 9090 M 900000
P 8989 L 500000
How do I count total transaction from two tables above in one month as per requested .
In example, request for total transaction in May so the result is like below
period | total
May 1275000
Thank you
Using MONTH(T1.date) = 5 and SUM(price) the expected result is achievable
SELECT MONTH(T1.date) AS Period, SUM(price) AS `Total`
FROM TableOne T1
JOIN TableTwo T2 ON T2.driver_number = T1.driver_number
WHERE MONTH(T1.date) = 5
GROUP BY MONTH(T1.date)

mysql- subtract values between rows where column values correspond

I have a table like:
Number | Event | Weight
1 4 150
1 4 160
2 5 200
2 4 200
3 6 190
3 6 195
For each row, I would like to subtract from its Weight, the Weight of another row where Number and Event matches (if exists). The desired output is:
Number | Event | Weight | DIFF
1 4 150 -10
1 4 160 10
2 5 200 NULL
2 4 200 NULL
3 6 190 -5
3 6 195 5
Is such an operation possible? Not sure if relevant, eventually I would need to turn this query into a view. Thanks in advance.
You need a left join:
select
t.*,
t.weight - tt.weight diff
from tablename t left join tablename tt
on tt.number = t.number and tt.event = t.event and tt.weight <> t.weight
It can be done by simply substracting the column in the joined table. When one of the operands is null, the result of the arithmetic operation is null:
select a.Number, a.Event, a.Weight, a.Weight - b.Weight as DIFF
from a
left join b on a.Number = b.Number and a.Event = b.Event

MySQL query find matching column based on another column?

Sorry I don't know how to word the question's title.
I have a table like this
Prod Part Number
0001 101 3
0001 102 2
0001 103 1
0002 101 3
0002 102 2
0002 103 4
0003 101 2
0003 102 3
0003 103 6
0004 101 3
0004 102 2
0004 103 1
I want to find the product that has the correct number per part for all parts.
So something like
SELECT Prod from table
WHERE (Number of Part(101)) = 3
AND (Number of Part(102)) = 2
AND (Number of Part(103)) = 1
Output would be:
Prod
0001
0004
How can I achieve that?
You could use some inner join
select t1.Prod from
( select Prod
from my_table
where part = 101
and Number = 3 ) t1
inner join
( select Prod
from my_table
where part = 102
and Number = 2 ) t2 on t1.Prod = t2.Prod
inner join
( select Prod
from my_table
where part = 103
and Number = 1 ) t3 on t1.Prod = t3.Prod
http://sqlfiddle.com/#!9/014fe4/8
Through conditional aggregation:
SELECT Prod,
SUM(CASE WHEN Part = 101 AND Number = 3 OR
Part = 102 AND Number = 2 OR
Part = 103 AND Number = 1
THEN 1 ELSE 0 END) sum
FROM tbl
GROUP BY Prod
HAVING sum = 3
This will give you an extra column. If it's a problem then wrap everything into another SELECT.

Add total of 3 rows for specific id

I have three tables:
Students
-------------------------------------------------------------
studentId first last gender weight
-------------------------------------------------------------
1 John Doe m 185
2 John Doe2 m 130
3 John Doe3 m 250
Lifts
-------------------
liftId name
-------------------
1 Bench Press
2 Power Clean
3 Parallel Squat
4 Deadlift
5 Shoulder Press
StudentLifts
------------------------------------------------
studentLiftId studentId liftId weight
------------------------------------------------
1 1 1 185
2 2 3 130
3 3 1 190
4 1 2 120
5 2 1 155
6 3 2 145
7 1 1 135
8 1 1 205
9 2 3 200
10 1 3 150
11 2 2 110
12 3 3 250
I would like to have four top lists:
Bench Press
Parallel Squat
Power Clean
Total of the above 3
I can successfully grab a top list for each specific lift using the following query:
SELECT s.studentId, s.first, s.last, s.gender, s.weight, l.name, sl.weight
FROM Students s
LEFT JOIN (
SELECT *
FROM StudentLifts
ORDER BY weight DESC
) sl ON sl.studentId = s.studentId
LEFT JOIN Lifts l ON l.liftId = sl.liftId
WHERE l.name = 'Bench Press'
AND s.gender = 'm'
AND s.weight > 170
GROUP BY s.studentId
ORDER BY sl.weight DESC
However, I am stuck on how to add the highest total of each lift for each student. How can I first find the highest total for each student in each lift, and then add them up to get a total of all three lifts?
Edit
The result set that I am looking for would be something like:
-------------------------------------------------
studentId first last weight
-------------------------------------------------
3 John Doe3 585
1 John Doe 475
2 John Doe2 465
I also forgot to mention that I would actually like two lists, one for students above 170 and one for students below 170.
SELECT -- join student a total weight to the student table
A.studentId,
A.first,
A.last,
C.totalWeight
FROM
Student A,
(
SELECT -- for each studet add the max weights
sum(B.maxWeight) as totalWeight,
B.studentID
FROM (
SELECT -- for each (student,lift) select the max weight
max(weight) as maxWeight,
studentId,
liftID
FROM
StudentLifts
GROUP BY
studentId,
liftID
) B
GROUP BY
studentId
) C
WHERE
A.studentID = C.studentId
-- AND A.weight >= 170
-- AND A.weight < 170
-- pick one here to generate on of the two lists.